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

时间:2016-03-31 08:28:42

标签: regex preg-replace regex-negation

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

/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

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

$pattern = '/(.*)(Itemid=)(?!527)([1-9]*)/';
$replacement = "494";
$row->text = preg_replace($pattern, '$1'.'$2'.$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, '$1'.'$2'."WTF?".$replacement, $row->text);

然后它看起来正常......但是在链接中有这个不需要的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

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

2 个答案:

答案 0 :(得分:1)

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

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

请参阅regex demo

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

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

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

并替换为'${1}'.$replacement

答案 1 :(得分:1)

试试这段代码:

$row->text = preg_replace($pattern, '$1'.'${2}'.$replacement, $row->text);

您之前的代码无效的原因是因为它加入了$2494,所以不是寻找 Capture Group#2 ,而是在寻找捕获组#2494 4494的第一位数字)。为避免此问题,请在号码周围添加{},以便4942

分开

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

如果您查看新的 Regex101 演示,您可以看到新的替补工作

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

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

(.*)(Itemid=)合并到(.*Itemid=)。这意味着您的Substituion可以成为这个,${1}494

还可以使用\d来选择一个数字,而不是[1-9](除非您不希望包含0,但这也是您在身份证中可能拥有的其他内容在你的RegEx中错过了)

Regex101 Demo

然后,你可以让它更安全,所以我会建议以下最终的RegEx和Substitution:

(.*Itemid=)(?!527$)(\d*)(.*)
${1}494$3

这允许Itemid之后的网址变量,例如...&Itemid=494&Foo=Bar

它还会阻止&Itemid=5279等ID未被选中

Regex101 Demo