2017-08-15 37 views
2

我現在的模式是這樣的: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

你想要從字符串的開始到匹配,然後是匹配,然後是匹配後的文本?你期望一個字符串中的單個匹配嗎? –

回答

-3

試試這個:

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

我已經嘗試過,但方括號不起作用。嘗試一下,它不起作用:regex101.com – Hasen

+0

對不起,看到更新的答案。適用於http://regexr.com。我錯過了'+'。 – DrRoach

+0

@Hasen它是否適用於'+'? – DrRoach

-1

對於剛剛匹配我還是你,這個工作對我來說:

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

我認爲人們只是回答得太快。我的問題的全部內容是沒有括號。不知道是否可以完成,但我已經在這裏列出了你的解決方案,在我的問題....我顯然知道如何做到這一點,但添加額外的括號是首先導致問題的原因。 – Hasen

+1

但這不是正常的括號,請注意'?:i'的用戶。這使得這個括號爲「非捕捉括號組」 –

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

您可能會「模糊」組名,使他們無法與用戶自定義模式發生衝突。或者讓用戶知道模式中不能使用哪些名稱。

注意s修改將使.匹配換行也是如此。

將上述溶液將mid組的最後發生匹配作爲第一start圖案是貪婪點圖案。如果您的字符串包含多個匹配項,並且您希望mid組匹配字符串中的第一個匹配項,請將(?<start>.*)替換爲(?<start>.*?)。否則,您需要決定算法應該是什麼樣的。

相關問題