V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
ZiShuo
V2EX  ›  PHP

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

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

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

    function cdn_replace($html){
    $cdnurl = "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   ·   我们的愿景   ·   实用小工具   ·   2827 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 14:03 · PVG 22:03 · LAX 07:03 · JFK 10:03
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.