PHP正则表达式匹配或者或不使用支架一个字?

PHP正则表达式匹配或者或不使用支架一个字?

问题描述:

我现在的模式是这样的:PHP正则表达式匹配或者或不使用支架一个字?

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"; 

的$值有时也有像上面的例子修饰符“如果(你|我)希望”,但其他的模式可能是简单地“接下来发生的事情”没有修饰符。所以额外的括号会导致一个问题,但我找不到另一种方法来做到这一点。

编辑:请注意,这里的问题是$ 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 

但它不是特别雄辩做!

+1

您的意思是'$ value'是否可以包含用户定义的模式?你不能使用非捕获组 - “”/(.*)(\bIf(?:I | you)want \ b)(。*)/ iu“' –

+0

不确定你的意思。问题出现在preg_replace中,它将三个括号内的查询替换为$ 1,$ 2和$ 3。如果你添加另一个支架*有时*,那么它显然不能正常工作。这就是为什么我需要这样做可能没有括号......或者必须有其他方式。 – Hasen

+0

你想要从字符串的开始到匹配,然后是匹配,然后是匹配后的文本?你期望一个字符串中的单个匹配吗? –

试试这个:

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

我已经尝试过,但方括号不起作用。尝试一下,它不起作用:regex101.com – Hasen

+0

对不起,看到更新的答案。适用于http://regexr.com。我错过了'+'。 – DrRoach

+0

@Hasen它是否适用于'+'? – DrRoach

对于刚刚匹配我还是你,这个工作对我来说:

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

我认为人们只是回答得太快。我的问题的全部内容是没有括号。不知道是否可以完成,但我已经在这里列出了你的解决方案,在我的问题....我显然知道如何做到这一点,但添加额外的括号是首先导致问题的原因。 – Hasen

+1

但这不是正常的括号,请注意'?:i'的用户。这使得这个括号为“非捕捉括号组” –

你的问题是,你不能依靠编号捕获组为其编号可能会有所不同,因为用户定义的模式部分可能包含任意数量的编号捕获组。

出路可以通过使用命名为捕获组。他们唯一的麻烦是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

您可能会“模糊”组名,使他们无法与用户自定义模式发生冲突。或者让用户知道模式中不能使用哪些名称。

注意s修改将使.匹配换行也是如此。

将上述溶液将mid组的最后发生匹配作为第一start图案是贪婪点图案。如果您的字符串包含多个匹配项,并且您希望mid组匹配字符串中的第一个匹配项,请将(?<start>.*)替换为(?<start>.*?)。否则,您需要决定算法应该是什么样的。