在 PHP 中,反向引用不起作用。

10

最近我一直在学习正则表达式(更准确地说是实践),并且我正在注意到它的强大之处。我提出了这个需求(链接),我知道'backreference'。我认为我理解它的工作原理,在JavaScript中可以使用,但在PHP中不行。

例如,我有这个字符串:

[b]Text B[/b]
[i]Text I[/i]
[u]Text U[/u]
[s]Text S[/s]

并使用以下正则表达式:

\[(b|i|u|s)\]\s*(.*?)\s*\[\/\1\]

regex101.com上测试是有效的,JavaScript也一样,但是在PHP中不起作用。

preg_replace的示例(不起作用):

echo preg_replace(
    "/\[(b|i|u|s)\]\s*(.*?)\s*\[\/\1\]/i", 
    "<$1>$2</$1>",
    "[b]Text[/b]"
);

虽然这种方法可行:

echo preg_replace(
    "/\[(b|i|u|s)\]\s*(.*?)\s*\[\/(b|i|u|s)\]/i", 
    "<$1>$2</$1>",
    "[b]Text[/b]"
);

我不明白我的错误在哪里,感谢所有帮助过我的人。

1个回答

15

原因是你使用了双引号字符串,在双引号字符串中,\1 被解释为一个字符的八进制表示(控制字符SOH=报头开始),而不是转义字符 1。

所以有两种方法:

使用单引号字符串:

'/\[(b|i|u|s)\]\s*(.*?)\s*\[\/\1\]/i'

或者转义反斜杠以获得字面上的反斜杠(用于字符串,而不是用于模式):

"/\[(b|i|u|s)\]\s*(.*?)\s*\[\/\\1\]/i"

此外,您可以像这样编写您的模式:

$pattern = '~\[([bius])]\s*(.*?)\s*\[/\1]~i';

// with oniguruma notation
$pattern = '~\[([bius])]\s*(.*?)\s*\[/\g{1}]~i';

// oniguruma too but relative:
// (the second group on the left from the current position)
$pattern = '~\[([bius])]\s*(.*?)\s*\[/\g{-2}]~i'; 

谢谢你的回答,我没有想到会犯这样的错误。然而我尝试使用带有 ~ (其实并不知道) 的模式,但是它不起作用,是吗? 但是它对于每个人都不起作用,还是我的理解错了? 链接 - mikelplhts
然而,你能简要解释一下(如果不打扰的话),/~ 之间的区别吗? - mikelplhts
1
@MicheleLapolla:你可以自由选择你想要的模式分隔符(http://php.net/manual/en/regexp.reference.delimiters.php),以避免在模式中转义字面斜杠,`~`是更好的选择。这三个模式都很好用,你可以在这里检查它们:https://eval.in/368317 - Casimir et Hippolyte

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接