php 检查 ncr 与负后视和贪婪不起作用

问题描述

我想找一个没有的错误NCR并补救,unicode是4或5个十进制数字,我写了这个PHP语句:

function repl0($m) {
    return '&#'.$m[0];
}
$s = "This is a good 23200; sample ship";
echo "input1= ".htmlentities($s)."<br>";
$out1=preg_replace_callback('/(?<!#)(\d{4,5};)/','repl0',$s);
echo 'output1 = '.htmlentities($out1).'<br>';

输出为:

input1= This is a good 23200; sample ship
output1 = This is a good 2&#3200; sample ship

根据输出消息,匹配只发生一次。 我想要的是匹配 '23200;'而不是'3200;'。 认应该是贪婪模式,我认为它会捕获 5 位数字而不是 4 位数字 我在这里误解了“贪婪”吗?我怎样才能得到我想要的?

解决方法

(?<!#)(\d{4,5};) 模式匹配如下:

  • (?<!#) - 匹配前面没有紧跟 #
  • 的位置
  • (\d{4,5};) - 然后尝试匹配并使用四位或五位数字以及紧跟在这些数字之后的 ; 字符。

所以,如果你有 #32000; 字符串输入,3 不能作为匹配的起始字符,因为它前面有 #,但 2 可以,因为它前面没有 # 并且有五位带有 ; 的数字用于匹配模式。

这里您需要的是通过向后视添加一个数字来遏制左侧的匹配,

(?<![#\d])(\d{4,5};)

使用此技巧,您可以确保匹配项不能紧跟在 # 或数字之前。

你说你最终使用了 (?<!#)(?<!\d)\d{4,5};,这个模式在功能上等同于上面的模式,因为后视,就像所有的环视一样,“站稳脚跟”,即当环视模式是时,正则表达式索引不会移动匹配。因此,对数字或 # 字符的检查发生在字符串中的相同位置。