Regex/通配符替换字符串PHP


Regex/wildcard replace on a string PHP

我有大量的文本被加载到标题中,其中包含这个链接。

<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"开头以/>结尾的字符串

我已经展示了我所追求的步骤,以及我的尝试。请帮助我写,并最终理解如何做到这一点。

您写的正则表达式到处都是。让我们看一下模式:

无论发生什么,它将以<link开始,以></link>/>结束(必须考虑到那些讨厌的不尊重标准的网络海盗)。您正在寻找rel参数,如果它有一个,并且它需要是规范的。

可以开始写正则表达式:#<link([^>]+)(/>|></link>)#is。这将映射所有link标签。然后可以使用简单的strpos调用解析参数。

如果您确定rel="canonical"将是链接标记的第一个参数,则可以将正则表达式进一步展开为#<link rel="canonical" href="?'?([^"']+)"?'?(/>|></link>)#is。这将按顺序映射它,如果您确定这将是顺序,这是很好的。

按出现顺序:

[^>]+匹配一次或多次>字符以外的任何字符

is标志表示:不区分大小写,不换行

"?'?匹配0或1 ',后面跟着0或1 '

如果还有什么不清楚的,请告诉我。

编辑:回答您的问题
  • //开始和结束表达式?它们被称为分隔符,它们将表达式"包围"起来。Perl正则表达式引擎允许针对表达式(i、s、g、b等)设置标志,这些标志必须在表达式之外。它们在分隔符之后——这就是分隔符的意义所在。你可以使用任何你喜欢的字符——它会选择最远的两个重复的字符。人们倾向于使用/,因为JS为他们使用了单个字符-我倾向于在PHP中使用#来清除HTML标签关闭时产生的/歧义。

  • ()指示单独的'表达式'必须匹配字符串返回?()匹配一个子集,如果您为匹配指定一个变量,则允许您在结果中获得它。正则表达式的每个部分都可以使用通配符&co,但只有封装在()中的内容将在matches

  • 中返回。
  • 以以下字符串开头的结果的^过滤器?不。a[]范围外的^将匹配开头的任何字符串。在新的一行,有效地,不仅仅是"words"。
  • $过滤器的结果,以以下字符串结束?和上面一样,只是"结束"而不是"开始"。

快速开始注意:不建议使用正则表达式解析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