仅替换body标签之间的所有图像src

时间:2013-07-07 20:13:50

标签: php regex html-parsing

我在php中有一个变量($ output),它包含将呈现给浏览器的所有html页面,但是我需要用data:image替换所有图像src以使lazyload js工作。

要求是:

  • img src没有相同的结构,我们有:

    < img src =" img.jpg" ALT ='' />

    < img alt =" text" SRC =' img.gif'>

    < img class =" myclass" SRC =" img.png" ALT ='' />

    ......等

  • 我只想替换介于< body {can have optional text}>之间的图片。和< / body>

  • 不要在< script {optional text here}>之间替换img标记。和< / script>

由于

1 个答案:

答案 0 :(得分:0)

许多人用正则表达式犯下的错误是试图编写一个能够完成所有事情的巨大正则表达式。这种方式就是疯狂。它不仅可能是不可能的(取决于问题),而且它将是复杂,丑陋和脆弱的。最好将事情分解为可控制的步骤。

您说您只想替换<img>中的<body>个标记,但唯一的地方<img>标记有效位于<body>之内,所以我会忽略这个。如果您确实需要忽略<img>之外的<body>标记,则可以将整个内容包装在另一个preg_replace_callback中以从您的输入中提取<body>

所以,我采用的方法是使用两个正则表达式:一个用于匹配输入中<img>标记的所有实例,另一个用于替换alt属性。为此,我使用preg_replace_callback

$output = preg_replace_callback( '/<img .*?>/', function($matches) {
        return preg_replace( '/\bsrc\s*=\s*[\'"](.*?)[\'"]/', 
            'data-image="$1"', $matches[0] );
}, $input );

请注意在重复元字符?上使用延迟量词*:如果没有这个,两个连续的<img>标记将被视为一个大标记,这不是我们想要的。在替换函数中,我查找src属性并将其替换为data-image属性。

以下是此解决方案失败的地方:

  • 如果您在引号分隔的src属性(<img src="what's_up_doc.jpg">)中有撇号,反之亦然。如果你需要解决这个问题,你必须有两个不同的替换正则表达式,一个用于处理双引号属性,另一个用于处理单引号属性。
  • 如果您的<img>代码跨越多行。如果这是一个问题,在外部正则表达式中,您可以使用[^]代替.来匹配所有内容,包括换行符。