PHP preg match / preg_replace无法识别模式

时间:2018-09-22 02:02:54

标签: php regex

我试图用分隔符标签替换仅包含一系列相同字符的段落的所有实例。

我已经使用https://www.phpliveregex.com/来测试代码,将代码直接从那里复制到服务器上的php上,并复制到http://phptester.net/上,但是无法正常工作。

示例:

$test = "<p>Sed nec convallis tortor. Aenean ante diam, aliquet eget porta in, cursus a nibh. Suspendisse eu tempus sem, sit amet malesuada arcu. Nunc condimentum a elit eget elementum. Curabitur id erat et dolor mattis luctus id id massa.</p>
<p>XXXXXXX</p>
<p><em>Nulla vel ligula arcu. Vivamus nec nisi sit amet dui vulputate suscipit.</em></p>
<p><em>Suspendisse finibus lectus ut elit molestie, ornare accumsan lacus accumsan.</em></p>
<p><em>Fusce vel blandit dolor, ac imperdiet purus.</em>.</p>";

echo preg_replace("/<p>(.)\1{3,}<\/p>/i", "<hr />", $test);

这仍将输出<p>XXXXXXX</p>行,而不是预期的<hr />行。

有什么想法吗?提示?

2 个答案:

答案 0 :(得分:1)

我可以通过将双引号替换为单引号来解决此问题。

echo preg_replace('/<p>(.)\1{3,}<\/p>/i', '<hr />', $test);

如果对模式中的1使用两个\\,则在对原始代码进行更多测试之后,也将起作用。像这样。

echo preg_replace("/<p>(.)\\1{3,}<\/p>/i", "<hr />", $test);

我认为这是因为使用双引号会将\1视为转义的1。在一个转义的反斜杠之前使用两个\\可以实现\1的所需指令。这样的事情。我的正则表达式不是很好,但是我认为这是正在发生的事情。您可以通过在模式周围使用单引号来避免所有这些情况。

答案 1 :(得分:1)

正如Joseph_J所指出的那样,问题在于\1必须传递给正则表达式引擎。这是一个长度为2的字符串,带有两个ASCII字符“ \”和“ 1”。但是在PHP "\[0-9]{1,3}"中(用双引号引起来)represents only one single character in octal notation。因此"\1"将是一个长度为1的字符串,由一个带ascii值1的字符组成。这是一个小概述:

source code     internal string     length
"\1"            ascii code 1        1
'\1'            \1                  2
"\\1"           \1                  2
'\\1'           \1                  2
"\134\61"       \1                  2

如果您还想覆盖换行符(“仅包含一系列相同字符”),则需要pattern modifier来使.也匹配换行符:

preg_replace('/<p>(.)\1*<\/p>/is', '<hr />', $test);