PHP正则表达式匹配一个单词或一个单词而不使用括号?

时间:2017-08-15 16:40:07

标签: php regex preg-replace preg-match

我目前的模式是:

pattern=("/(.*)(\bIf you want\b)(.*)/iu");

但是:

preg_replace($pattern, '$1*$2*$3', $result);

所以这三个部分必须按$ 1,$ 2和$ 3进行替换,但我想允许一些进一步的灵活性,所以我可以检测这两行:

If you want
If I want

所以我可以这样做:

pattern=("/(.*)(\bIf (I|you) want\b)(.*)/iu");

但由于我需要更换$ 1,$ 2和$ 3,因此会产生问题。模式是动态插入的,因此都是不同的:

$pattern = "/(.*)(\b".$value."\b)(.*)/iu";

$ value有时会有一个修饰符,如上例和#34;如果(你|我)想要"但其他模式可能只是"接下来发生的事情"没有修饰语。因此额外的括号会引起问题,但我无法找到另一种方法。

编辑:请注意这里的问题是$ 1,$ 2和$ 3 preg_replace。使用类似

的模式
"/(.*)(\bwhat happened next\b)(.*)/iu" 

这很好,但还有一个像

这样的附加支架
"/(.*)(\bIf (I|you) want\b)(.*)/iu"

它不会被$ 1,$ 2和$ 3 preg_replace正确替换。

我也意识到可以这样做

 If you want|If I want

但它并不是特别雄辩!

3 个答案:

答案 0 :(得分:0)

您遇到的问题是您不能依赖编号捕获组,因为它们的数量可能会有所不同,因为用户定义的模式部分可能包含任意数量的编号捕获组。

可以通过使用命名捕获组来解决问题。它们唯一的问题是PHP不支持替换模式中的命名反向引用。可以使用preg_replace_callback函数解决它:

$s = 'text If you want this';
echo preg_replace_callback("/(?<start>.*)(?<mid>If (I|you) want)(?<end>.*)/siu", function($m) {
    return $m['start'].'*'.$m['mid'].'*'.$m['end'];
}, $s);
// => text *If you want* this

请参阅PHP demo

你可以&#34;混淆&#34;组名,以便它们不会与用户定义的模式冲突。或者让用户知道模式中不能使用哪些名称。

注意s修饰符也会使.匹配换行符。

上述解决方案将与mid组的 last 匹配项匹配,因为第一个start模式是贪婪点模式。如果您的字符串包含多个匹配项,并且您希望mid组匹配字符串中的第一个匹配项,请将(?<start>.*)替换为(?<start>.*?)。否则,您需要确定算法应该是什么样的。

答案 1 :(得分:-1)

只为匹配我或你,这对我有用:

$pattern=("/(.*)(\bIf (?:i|you) want\b)(.*)/iu");

答案 2 :(得分:-3)

试试这个:

pattern=("/(.*)(\bIf [I|you]+ want\b)(.*)/iu");