正则表达式 - 如果数字不等于调试问题则替换

Regex - Replace if number not equal debug issue

有人能告诉我我做错了什么吗?这是我的示例数据:

/docman/?view=document&alias=690-uchwala-rady-miasta-nr-xv-100-2015-zmieniajaca-uchwale-nr-xxxiii-151-2012&category_slug=gminne-programy-i-strategie&Itemid=123
/docman/?view=document&alias=690-uchwala-rady-miasta-nr-xv-100-2015-zmieniajaca-uchwale-nr-xxxiii-151-2012&category_slug=gminne-programy-i-strategie&Itemid=494
/docman/?view=document&alias=690-uchwala-rady-miasta-nr-xv-100-2015-zmieniajaca-uchwale-nr-xxxiii-151-2012&category_slug=gminne-programy-i-strategie&Itemid=527

我需要搜索与 527 不同的 Itemid,并将数字替换为 494。这是我的代码:

$pattern = '/(.*)(Itemid=)(?!527)([1-9]*)/';
$replacement = "494";
$row->text = preg_replace($pattern, ''.''.$replacement, $row->text);

我收到了这样的东西

/docman/?view=document&alias=690-uchwala-rady-miasta-nr-xv-100-2015-zmieniajaca-uchwale-nr-xxxiii-151-2012&category_slug=gminne-programy-i-strategie&94=
/docman/?view=document&alias=690-uchwala-rady-miasta-nr-xv-100-2015-zmieniajaca-uchwale-nr-xxxiii-151-2012&category_slug=gminne-programy-i-strategie&94=
/docman/?view=document&alias=690-uchwala-rady-miasta-nr-xv-100-2015-zmieniajaca-uchwale-nr-xxxiii-151-2012&category_slug=gminne-programy-i-strategie&Itemid=527

这在 RegExr 上不能正常工作,但可以(虽然带有 g 标志)。

现在,如果我像这样在第二个表达式之后添加一些内容:

$row->text = preg_replace($pattern, ''.''."WTF?".$replacement, $row->text);

然后它开始看起来不错......但是 link:

中有这个不需要的 WTF
/docman/?view=document&alias=690-uchwala-rady-miasta-nr-xv-100-2015-zmieniajaca-uchwale-nr-xxxiii-151-2012&category_slug=gminne-programy-i-strategie&Itemid=WTF?494
/docman/?view=document&alias=690-uchwala-rady-miasta-nr-xv-100-2015-zmieniajaca-uchwale-nr-xxxiii-151-2012&category_slug=gminne-programy-i-strategie&Itemid=WTF?494
/docman/?view=document&alias=690-uchwala-rady-miasta-nr-xv-100-2015-zmieniajaca-uchwale-nr-xxxiii-151-2012&category_slug=gminne-programy-i-strategie&Itemid=527

我不明白。我做错了什么,我该如何调试? :(

使用大括号以明确的方式定义捕获组 ID:

$row->text = preg_replace($pattern, ''.''.$replacement, $row->text);
                                           ^^^

regex demo

由于 $replacement 以数字开头,正则表达式引擎正在寻找捕获组 #24 值(</code> 被解析为第 24 个捕获组)。为避免这种情况,请在替换模式中的 <code>$ 之后在组 ID 周围使用大括号。或者使用命名捕获来完全避免这个问题。

我还建议在模式 ((?!527$)) 中的 527 之后添加 $,以免排除以 527 开头的 ID。当然,您可以将前 2 组合并为一个,并使用 [0-9] 而不是 [1-9] 来匹配像 206 这样的 ID,其中 0 可以出现在里面,并删除不必要的捕获来自 [0-9]* 的群组:

(.*Itemid=)(?!527$)[0-9]*
                 ^

并替换为 ''.$replacement.

试试这个代码:

$row->text = preg_replace($pattern, ''.''.$replacement, $row->text);

您之前的代码不起作用的原因是因为它加入了 </code> 和 <code>494,而不是寻找 Capture Group #2 ,它正在寻找 Capture Group #24944494 的第一个数字)。因此,为避免此问题,请在数字周围添加 {},以便它看到 4942

分开

如果您查看此 Regex101 演示,您可以看到 Substitute 部分中的错误,以红色突出显示

如果您查看新的 Regex101 演示,您可以看到新的 Substitute 正在运行


此外,您可以将 RegEx 更改为更短、更高效:

(.*Itemid=)(?!527)(\d*)

(.*)(Itemid=)合并为(.*Itemid=)。这意味着你的替换可以变成这样,494

也使用 \d 来 select 一个数字,而不是 [1-9](除非你不希望包含 0,但那是你可以您的 ID 中有您在 RegEx 中遗漏的内容)

Regex101 Demo


然后,你可以让它更安全,所以我建议使用以下最终 RegEx 和替换:

(.*Itemid=)(?!527$)(\d*)(.*)
494

这允许 Itemid 之后的 URL 个变量,像这样 ...&Itemid=494&Foo=Bar

它还会阻止像 &Itemid=5279 这样的 ID 不被 selected

Regex101 Demo