2017-04-26 43 views
2

所有的話,我有以下形式獲得具有不特定的前綴組

$string = "This is {test} for [a]{test2} for {test3}."; 

我想不是由方括號前綴的大括號的字符串。因此,在上面的字符串中,我想獲得{test}{test3},但不是[a]{test2}

我在回答https://stackoverflow.com/a/977294/2311074中發現,這可能是負面的預測。所以我試了

$regex  = '/(?:(?!\[[^\}]+\])\{[^\}]+\})/'; 
    echo preg_match_all($regex, $string, $matches) . '<br>'; 
    print_r($matches); 

但這仍然給我所有三個大括號。

陣列([0] =>數組([0] => {測試} [1] => {TEST2} [2] => {TEST3}) )

爲什麼這不起作用?

+0

@WiktorStribiżew感謝您的詳細解答。我正在追趕這個主題的負面看法。一旦我理解了,我會立即回覆/提出你的回答。 – Adam

+0

請問什麼是不清楚的 - 我將在網上幾個小時。 –

回答

1

您正則表達式失敗的原因是,它的任何{(接着用1 +非}秒,然後一})如果不啓動排除模式內模式的序列相匹配,一個[,1+字符除了},然後是](並且總是如此,因此,您將得到所有{...}子字符串)。

使用(*SKIP)(*FAIL) technique

\[[^]]*]\{[^}]+}(*SKIP)(*F)|\{[^\}]+} 

regex demo

詳細

  • \[[^]]*]\{[^}]+}(*SKIP)(*F) - 匹配
    • \[ - 一個[
    • [^]]* - 比0+字符等]
    • ]\{ - ]{
    • [^}]+ - 1+字符比]
    • }其他 - 文字}
    • (*SKIP)(*F) - PCRE動詞到目前爲止丟棄匹配的文本,並迫使引擎去尋找從當前位置的下一場比賽(好像比賽發生)
  • | - 或
  • \{[^\}]+}
    • \{ - 文字} - 一個{
    • [^\}]+ - 比}
    • }其他1+字符。

PHP demo

$string = "This is {test} for [a]{test2} for {test3}."; 
$regex  = '/\[[^]]*]\{[^}]+}(*SKIP)(*F)|\{[^}]+}/'; 
echo preg_match_all($regex, $string, $matches) . "\n"; 
print_r($matches[0]); 

輸出:

2 
Array 
(
    [0] => {test} 
    [1] => {test3} 
) 
+0

謝謝。我只是意識到我的rexgex有一個錯誤,我實際上想使用'/(?<!\ [[^ \}] + \])\ {[^ \}] + \} /''但是這個不工作,因爲**「lookbehind斷言必須是固定長度」** http://stackoverflow.com/questions/3796436/whats-the-technical-reason-for-lookbehind-assertion-must-be-fixed-長度在-R。所以在這裏使用跳過失敗方法是有道理的,而不是倒退。謝謝! – Adam

+0

很高興我能幫到你。 '(* SKIP)(* FAIL)'是唯一正確的方式否定PCRE中的某些東西,而無需進行假設,否則無法訪問負向無限寬度的後視圖。 –

2

如果您確信打開花括號只會用方括號對(平衡)開頭,然後負面後顧之心將會做到這一點:

(?<!]){[^}]*} 

Live demo

+0

非常好的提示,謝謝:)!是否有必要轉義']和'}'? – Adam

相關問題