在PHP中,对字符串进行正则表达式/通配符替换

4

我有一大段文本加载到头部,其中包含这个链接。

<link rel="canonical" href="could_be_anything_here_at_all" />

我希望用一个新值替换它,但是href会根据页面的意思而改变,因此简单的 str_replace 不可行。
我尝试使用 preg_replace,但无法理解这似乎是一个简单问题。
    $regex = '/(^<link rel="canonical")(\/>$)/';
    $match = preg_match_all($regex, $content, $matches);
    var_dump($matches);
  • / /开始和结束的表达式是什么?
  • ()表示需要匹配的“表达式”应该分开,以便返回字符串?
  • ^过滤以以下字符串开头的结果?
  • $过滤以以下字符串结尾的结果?

因此,我正在寻找以<link rel="canonical"开头并以/>结尾的字符串。

我展示了我想要的步骤,以及我的尝试。请帮我编写并最终理解如何执行此操作。对于这个问题,我真的不知所措。


2
+1个很好的示例,展示了如何在SO上提问。 - michi
在响应中即时处理HTML是一个不好的想法。最好的解决方案是更改定义HTML的位置。你有没有查看过它的定义位置? - Sverri M. Olsen
2个回答

2
你写的正则表达式太混乱了。让我们来看一下模式:
无论发生什么,它都将以 `` 或 `/ >` 结束(必须考虑那些不遵守标准的网络海盗)。您要查找 rel 参数,如果有一个,则需要是 canonical。
我们可以开始编写正则表达式:`#<link([^>]+)(/>|></link>)#is`。这将映射所有 `link` 标签。然后,您可以使用简单的 `strpos` 调用解析参数。
如果您确定 rel="canonical" 将是链接标记的第一个参数,则可以将正则表达式进一步扩展为 `#<link rel="canonical" href="?'?([^"']+)"?'?(/>|></link>)#is`。这将按顺序映射它,如果您确定这将是顺序,则很好。
按照出现的顺序:
`[^>]+` 匹配除 `>` 字符之外的任何字符一次或多次
`i` 和 `s` 标志分别表示:不区分大小写,不在换行符处中断
`"?'?` 匹配 0 或 1 个 ",后跟 0 或 1 个 '。
如果还有什么不清楚的,请告诉我。
编辑:回答您的问题
- `/ /` 开始和结束表达式? 它们称为定界符,并且“包围”表达式。Perl 正则表达式引擎允许设置有关表达式的标志(i、s、g、b 等),并且这些标志必须在表达式之外。它们在分隔符之后 - 这就是分隔符的作用。您可以使用任何字符 - 它将选择最远的两个重复字符。人们倾向于使用 /,因为 JS 使用该单个字符 - 我倾向于在 PHP 中使用 # 来清除 / 由于关闭 HTML 标记而产生的歧义。
- () 表示需要匹配的单独“表达式”吗? () 匹配子集,并允许您在匹配中指定变量以获取其结果。正则表达式的每个部分都可以使用通配符等,但只有括在 () 中的内容才会在匹配中返回。
- ^ 过滤以以下字符串开头的结果? 不是的。[] 范围外的 ^ 将匹配任何以以下字符串开头的内容。在新行上,有效地不仅仅是“单词”。
- $ 过滤以以下字符串结尾的结果? 与上面相同,只是“结束”而不是“开始”。

@MarkPurnell:顺便提一下,Perl兼容的正则表达式引擎使用了更多的符号。值得一读——如果正确使用,这些东西是无限强大的。 - Sébastien Renauld

1

快速起步提示:不建议使用正则表达式解析HTML,而应该使用DomDocument或其他“DOM解析”插件。但由于这只是使用一个句子字符串,这是我处理它的方法:

<?php
// base string
$str = '<link rel="canonical" href="could_be_anything_here_at_all" />';

// for preg_replace
$preg_replace = '<link rel="canonical" href="'.preg_replace('/<link rel="canonical" href="(.*)" \/>/','MY_NEW_LINK',$str).'" />';
echo $preg_replace;

// preg_match_all
preg_match_all('/<link rel="canonical" href="(.*)" \/>/',$str,$preg_match);
echo '<pre>',print_r($preg_match),'</pre>'; // process as you wish

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接