求正则高手帮忙解决一个正则表达式的问题 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
ZiShuo
V2EX    PHP

求正则高手帮忙解决一个正则表达式的问题

  •  
  •   ZiShuo 2016-04-25 09:32:01 +08:00 3802 次点击
    这是一个创建于 3541 天前的主题,其中的信息可能已经有所发展或是发生改变。
    由于最近流量暴涨,以前的老站后台没有设置静态文件的 CDN 接口。于是就想在入口文件加入一个用正则替换的静态文件的功能。自己参照网上写了下面的替换函数,能够解决大部分的静态文件,但是一旦遇上了以 http 、 https 或者 //开头的数据的数据就出错了。我知道咱站里面的技术大牛多,所以想请大牛们帮我下面这个函数改成能够除非以 http 、 https 或者 //开头的数据,也是排除原来本身就引用了外链的部分。

    另外不要让我用全站 CDN 加速,因为业务限制,不太方便。我只想把特定后缀的文件的流量转移到 CDN 上面去。

    function cdn_replace($html){
    $cdnurl = quot;http://www.zishuo.net/"; //cdn Url
    $exts = 'jpg|jpeg|gif|png|bmp|webp|css|js'; //扩展名(使用|分隔)
    $regex = '/([^\s\?\\\'\"\;\>\<]{1,}.(' . $exts . '))([\"\\\'\s\?]{1})/';
    $cOntent= preg_replace($regex, $cdnurl. '$1$3', $html);
    return $content;
    }
    15 条回复    2016-04-27 09:54:34 +08:00
    thinkmore
        1
    thinkmore  
       2016-04-25 09:49:26 +08:00
    能给出具体要求吗?比如说运行环境。原始文本。期望结果等。
    比如: js
    原始文本: http://www.baidu.com/show.html
    期望文本: www.baidu.com/show.html (不获取协议头)
    ango
        2
    ango  
       2016-04-25 10:35:16 +08:00
    前端外部资源,无非就这两类: href 、 src 。(周一脑子就像浆糊,是否还有其它实在想不起了)。
    以这些标识开头,以指定 CDN 资源类型结尾, replace 一下就好了。
    ango
        3
    ango  
       2016-04-25 11:17:26 +08:00
    @ango
    $cdnUrl = 'http://www.zishuo.net/';
    $exts = 'jpg|jpeg|gif|png|bmp|webp|css|js';
    $pattern = "/((?:src|href)=[\"\']?)((?:http|https)?\/\/[^\/]+\/)(.+?\.(?:{$exts}))/";
    //preg_match_all($pattern, $html, $matches);
    $html = preg_replace($pattern, "\\1{$cdnUrl}\\3", $html);

    另外,简单点可以用 preg_replace_callback 来处理的,简单正则找到要替换要位置后,用 callback 来判断一下是否需要处理。
    jackal
        4
    jackal  
       2016-04-25 12:40:18 +08:00
    我还算熟悉正则表达式。
    但是对 PHP 不熟悉,对你的业务(想替换的文件是哪一些)也不熟悉。

    我猜你想要的是找人帮你修改一下正则表达式,能更好地匹配。

    麻烦你把规则说清楚,给一些例子,哪一些是匹配的,哪一些不需要匹配。

    然后我们把修改好的正则表达式贴给你。
    ZiShuo
        5
    ZiShuo  
    OP
       2016-04-25 14:19:01 +08:00
    @thinkmore
    @ango
    @jackal

    是 PHP 的,举个例子吧?

    我原本网页里面的图片地址是以下这种路径:

    xxx/logo.jpg
    /xxx/logo.jpg
    ./xxx/logo.jpg

    现在我想将网页里面所有这种路径的都替换成下面这种 url :

    http://www.zishuo.net/xxx/logo.jpg
    ZiShuo
        6
    ZiShuo  
    OP
       2016-04-25 14:19:53 +08:00
    简单来说就是将
    ZiShuo
        7
    ZiShuo  
    OP
       2016-04-25 14:21:29 +08:00
    简单来说就是将

    <img alt="" src="index/a14.jpg" width="320" height="207" />
    替换成
    <img alt="" src="http://www.zishuo.net/index/a14.jpg" width="320" height="207" />

    但是不仅仅限于图片,整个替换资源的类型为:

    jpg|jpeg|gif|png|bmp|webp|css|js
    imn1
        8
    imn1  
       2016-04-25 14:44:05 +08:00
    感觉在 http sever 做 redir 跳转更简单些
    ./ 这种是相对路径,确定直接换成 CDN 的根?
    ZiShuo
        9
    ZiShuo  
    OP
       2016-04-25 16:10:36 +08:00
    @imn1 基本上是可以确认我就是那三种路径,即使替换成 CDN 的根也是没影响的。我现在自己的那个替换函数是可以用的,但是要是存在 http 、 https 、//这种开头的外链路径就出错了,所我希望像 @jackal 说的一样,请人帮我修改一下正则表达式,能更好地匹配。排除以 http 、 https 或者 //开头的外链地址。
    imn1
        10
    imn1  
       2016-04-25 16:16:32 +08:00
    ^(?!http|//).*jpg$
    中间.*部分自己举一反三吧
    cxbig
        11
    cxbig  
       2016-04-25 16:24:50 +08:00
    这种需求不应该 PHP 来做吧?在 Nginx 或 Apache 里写规则快多了。
    thinkmore
        12
    thinkmore  
       2016-04-26 10:27:26 +08:00
    ((\.)?(/)?\w+/\w\.(jpg|jpeg|gif|png|bmp|webp|css|js))这个正则可以匹配你的资源。然后你替换下就行了.

    不满足的稍微调试下就行了
    ZiShuo
        13
    ZiShuo  
    OP
       2016-04-26 15:48:45 +08:00
    @thinkmore 能帮忙写个完整的替换函数吗?我用你那么替换上去后什么都匹配不出来了。
    jackal
        14
    jackal  
       2016-04-26 17:12:58 +08:00
    我跟你 @ZiShuo 讲,需求要这样表达才算清楚明了, 请你确认一下,然后朋友们帮你出正则表达式和替换了。
    1 )资源一定是被“” ‘’(双引号,单引号)来包围括起来的
    2 )资源结尾是 .(jpg|jpeg|gif|png|bmp|webp|css|js) ()括起来是限定“或者“的范围
    3 )文件名肯定是 x/y.jpg 等 , x,y 可以是 1 个或者多个字符, x 表示目录名, x 可能是为空(没有目录,直接 y.jpg )或者多重目录(x/y/z.jpg 这样的)
    字符的话, 是大小写字母和数字和-_(横杠和下划线)字符
    4 )资源的协议,有可能是无协议,比如只是 src="index/a14.jpg";
    但是也有可能是 http://www.abc.com/index/a14.jpg (请你考虑好这种情况的可能性,没有的话最好)
    thinkmore
        15
    thinkmore  
       2016-04-27 09:54:34 +08:00
    @ZiShuo 我不会写 php 的。我给你写了一个 js 版本的。你根据你的语法进行具体转换下吧

    result = http://www.baidu.com/abc/test.do.replace(/\.?\/?(\w+\/\w+\.(jpg|jpeg|gif|png|bmp|webp|css|js))/mg, "http://www.zishuo.net/$1");

    http://www.baidu.com/abc/test.do 换成你的匹配串就行了
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2928 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 26ms UTC 13:55 PVG 21:55 LAX 05:55 JFK 08:55
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86