如何用小胡子表达式替换文档中的 img src 和 link href?

How to replace img src and link href in a document with a mustache expression?

我尝试替换 srchref 值,但使用 regex

进行了小的修改

简单示例

//Find:
<img src="icons/google-icon.svg" > 
//Replace to: 
<img src="{{asset('icons/google-icon.svg')}}" >

//Find:
<link href="css/style.css"> 
//Replace to: 
<link href="{{asset('css/style.css')}}">
/** etc... */

现在这是我的正则表达式:

//Find:
src\s*=\s*"(.+?)" 
//Replace to:
src="{{ asset('') }}"

它的工作实际上非常好,但它仅适用于 src 而不是 [hrefsrc],而且我想排除包含 {{asset[ 的任何值=20=]

有什么想法吗?提前致谢

您可以使用交替来匹配 srchref,然后使用否定前瞻来断言 src/href 不以 {{asset 开头:

((?:src|href)\s*=\s*")((?!{{\s*asset)[^"]+)

Demo on regex101

这还将更改 <a> 标签内或其他地方的 href 属性。如果这是一个问题,请改用 DOMDocument 解决方案。请注意,如果您的 HTML 不仅仅是一个片段,那么您不需要在对 loadHTML 的调用中在其周围添加 div 标记,并且最后一行应更改为 echo substr($doc->saveXML(), 38);.

$html = <<<EOT
//Find:
<img src="icons/google-icon.svg" > 
//Replace to: 
<img src="{{asset('icons/google-icon.svg')}}" >

//Find:
<link href="css/style.css"> 
//Replace to: 
<link href="{{asset('css/style.css')}}">
/** etc... */
<a href="http://www.example.com">
EOT;

$doc = new DOMDocument();
$doc->loadHTML("<div>$html</div>", LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);

$xpath = new DOMXPath($doc);
foreach ($xpath->query('//img') as $img) {
    $src = $img->getAttribute('src');
    if (preg_match('/^(?!{{\s*asset).*$/', $src, $m)) {
        $img->setAttribute('src', "{{asset('" . $m[0] . ")'}}");
    }
}

foreach ($xpath->query('//link') as $link) {
    $href = $link->getAttribute('href');
    if (preg_match('/^(?!{{\s*asset).*$/', $href, $m)) {
        $link->setAttribute('href', "{{asset('" . $m[0] . ")'}}");
    }
}

// strip XML header and added <div> tag
echo substr($doc->saveXML(), 44, -6);

输出:

//Find:
<img src="{{asset('icons/google-icon.svg)'}}"/> 
//Replace to: 
<img src="{{asset('icons/google-icon.svg')}}"/>

//Find:
<link href="{{asset('css/style.css)'}}"/> 
//Replace to: 
<link href="{{asset('css/style.css')}}"/>
/** etc... */
<a href="http://www.example.com"/>

Demo on 3v4l.org

Nick 是正确的 can/should 使用 DomDocument 完成。

另外值得一提的是 a buggy side-effect when adding curly braces to the attribute strings (they get encoded) when using saveHTML() 访问变异文档。要解决此问题,请使用 saveXML() 并 trim 去掉文档前面的 xml 标签。

我将您的示例标签包装在父标签中,这样 DomDocument 就可以正常运行,而不会破坏您的文档结构。这对您的项目来说可能是不必要的预防措施。

我的代码片段使用 XPath 直接定位符合条件的属性,并在没有任何正则表达式的情况下替换它们的值。我的 xpath 表达式中的管道 (|) 表示 "or" - 因此它针对 img 标签的 src 属性或 link 标签的 href 属性。

代码:(Demo)

$html = <<<HTML
<div>
    <img src="icons/example.svg">
    <a href="http://www.example.com">a link</a>
    <link href="css/example.css">
    <iframe src="http://www.example.com/default.htm"></iframe>
</div>
HTML;

$dom = new DOMDocument();
$dom->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
$xpath = new DOMXPath($dom);
foreach ($xpath->query('//img/@src | //link/@href') as $attr) {
    $attr->value = "{{asset('" . $attr->value . "')}}";
}
echo substr($dom->saveXML(), 38);  // remove the auto-generated xml tag from the start

输出:

<div>
    <img src="{{asset('icons/example.svg')}}"/>
    <a href="http://www.example.com">a link</a>
    <link href="{{asset('css/example.css')}}"/>
    <iframe src="http://www.example.com/default.htm"/>
</div>

糟糕,我刚刚看到你问题中的最后一个请求。

not()starts-with() 的实施应用于这两个标记,以取消已转换为小胡子代码的元素的资格。

新的 xpath 表达式:(Demo)

//img[not(starts-with(@src,"{{asset"))]/@src | //link[not(starts-with(@href,"{{asset"))]/@href