【问题标题】:Change the src part of an img tag更改 img 标签的 src 部分
【发布时间】:2020-07-01 05:51:57
【问题描述】:

我有一个包含 html 代码的字符串,我想在每次出现在字符串中时将 <img src="anything.jpg"> 更改为 <img src="'.DOC_ROOT .'anything.jpg">。我真的不想想要使用 html 解析器,因为这将是我将使用它的唯一目的。有谁知道如何在 php 中执行此操作,例如使用正则表达式?

【问题讨论】:

  • 你似乎知道去哪里找。您是否尝试过使用正则表达式?
  • 嗯,我试过了,但我对正则表达式不太擅长,我试过的都没有用
  • coderwall.com/p/on3ffa 20 秒搜索...
  • 那是一个解析器,对吧?
  • @Jonan 是的,但是 the DOM extension 应该内置到您的 PHP 安装中,而不需要任何额外的代码,并且与基于字符串的解决方案相比,它不太可能导致微妙的问题。

标签: php html regex


【解决方案1】:

really should use a parser,但既然你明确表示你真的不想这样做,你可以使用以下regex replace

$string = preg_replace('/<img([^>]*)src=["\']([^"\'\\/][^"\']*)["\']/', '<img\1src="'.DOC_ROOT.'\2"', $string);

Demo。此正则表达式不会修改任何已经是相对路径的 url。如果您确实想匹配这些,请将其更改为以下内容:

$string = preg_replace('/<img([^>]*)src=["\']["\'\\/]?([^"\']*)["\']/', '<img\1src="'.DOC_ROOT.'\2"', $string);

Demo.

【讨论】:

  • 这是一个很好的例子,说明了正则表达式解决方案的脆弱性。这会失败的几种情况:1)如果imgsrc之间有多个空格; 2) 如果 HTML 包含 XML 样式的自闭合标签 (&lt;img src="foo.jpeg" /&gt;); 3) 如果 HTML 在属性周围使用单引号,而不是双引号; 4) 如果 img 标签包含其他属性,例如classid; 5) 如果 HTML 包含不需要前缀的 URL,例如URL 已经指向不同的域。
  • @IMSoP 我意识到这一点,这就是为什么我提醒 OP 他实际上不应该这样做。不过我会稍微改进一下我的正则表达式。
  • 是的,正则表达式解决方案仍然比这个解决方案好很多。问题 1、2 和 3 很容易解决; 4 有点棘手,因为您不想假设 srcfirst 属性。 5 是最难的,但您可以使用否定断言忽略以 http 开头的属性,或使用 preg_replace_callback 让替换通过回调函数运行。
  • @IMSoP 我想我已经很好地解决了这 5 个问题。有什么方法你能想到它仍然会坏吗?
  • 不错。我敢肯定仍然存在边缘情况 - HTML 是一种非常宽容的语言,所以有很多方法可以编写相同的东西 - 但随着正则表达式的发展,这可能不是一个糟糕的选择。
【解决方案2】:

如果您绝对必须使用正则表达式而不是 DOM 解析器,您可以使用它。

不确定 DOC_ROOT 来自何处,因为它不是有效的 PHP 变量(可能是常量?)。另请注意,如果您有单引号,您将无法在字符串中使用嵌入式变量。

你可能想要更多类似的东西:

img.*?src=['"](.*?)['"]

替换为:

img src="$_SERVER['DOCUMENT_ROOT']$1"

转换:

echo "<img src='anything.jpg'>"; //into:
echo "<img src='$_SERVER[\'DOCUMENT_ROOT\']/anything.jpg'>";

http://regex101.com/r/vN7lN9

在 php 中,代码如下所示:

$string = "<img src='anything.jpg'>";
echo preg_replace('/img.*?src=[\'\"](.*?)[\'\"]/', "img src='$_SERVER[DOCUMENT_ROOT]/$1'", $string);

请注意,如果您的 DOM 包含不规则的 HTML(标签错位,= 符号之间的空格),您最终可能会导致很多问题。这就是像 这样的 DOM 解析器派上用场的地方。

【讨论】:

  • DOC_ROOT 这样的裸词表示constant。但是,您的示例包含无效常量 DOCUMENT_ROOT - 您应该引用密钥,如 $_SERVER['DOCUMENT_ROOT']
  • @IMSoP 我将它写在字符串中——只是没有在示例中包含该位。现在已经修好了。
  • 我指的是这一行:img src='$_SERVER[DOCUMENT_ROOT]$1' - DOCUMENT_ROOT 周围没有引号。
  • 另外,虽然正则表达式看起来不错,但在这个答案中,您实际上如何将它与 PHP 一起使用并不是很清楚,因为您显示的代码行本身都不是有效的 PHP。
  • @IMSoP 在一个完全有效的字符串中。或者,如果你真的想要它,它可以有{}。至于 php 实现,有无数关于使用 preg_replace 的问题和说明。
【解决方案3】:

很多人都说明了使用 DOM 解析器的重要性,但真正说明如何执行任务的答案太少了。

正则表达式,即使在试图编写单行或更改单个字符时,也不适合解析 html,因为它对 DOM 无知——它处理您的输入为字符串,仅此而已。我已经制作了一个演示,说明正则表达式(来自接受的答案)将如何进行意外替换。

代码:(Demo)

$html = <<<HTML
<p>Some random text <img src="anything.jpg"> text <iframe data-whoops="<img" src="anything.jpg"></iframe></p>
HTML;

define('DOC_ROOT', 'www.example.com/');

echo "With regex:\n";
echo preg_replace('/<img([^>]*)src=["\']([^"\'\\/][^"\']*)["\']/', '<img\1src="'.DOC_ROOT.'\2"', $html);

echo "\n\n---\n\nWith a parser:\n";

$dom = new DOMDocument;
$dom->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
foreach ($dom->getElementsByTagName('img') as $img) {
    $img->setAttribute('src', DOC_ROOT . $img->getAttribute('src'));
}
echo $dom->saveHTML();

输出:

With regex:
<p>Some random text <img src="www.example.com/anything.jpg"> text <iframe data-whoops="<img" src="www.example.com/anything.jpg"></iframe></p>

---

With a parser:
<p>Some random text <img src="www.example.com/anything.jpg"> text <iframe data-whoops="&lt;img" src="anything.jpg"></iframe></p>

如果您需要对 img 标签的 url 进行有条件的替换,可以使用其他工具(如 url 解析器或 Xpath)来满足您的要求。

https://stackoverflow.com/a/60263813/2943403

最后,我的建议是忘记你写了多少行代码;只需编写健壮/可靠的代码。

【讨论】:

    【解决方案4】:

    这就是你要找的,我想:

    $pictureName = 'anything.jpg';
    
    $html = str_replace($pictureName, DOC_ROOT.$pictureName, $html);
    

    【讨论】:

    • “anything.jpg”只是一个例子。我希望每个图像 src 都将 DOC_ROOT 放在它前面。不过谢谢:)
    猜你喜欢
    • 2012-07-28
    • 2021-05-15
    • 2021-07-19
    • 1970-01-01
    • 2013-05-23
    • 2012-09-16
    • 2010-09-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多