2012-04-30 17 views
1

我想創建一個正則表達式(在PHP)匹配這些文本:表達與多個{}塊

#{text} 
#{text1}{text2} 
#{text1}{numbers}{text2} 
#{text1}{text with spaces}{numbers}{text2} 

等等。基本上第一個街區只能容納沒有空間的文字,其餘的則可以容納任何東西。之後,獲取匹配那些text1 ...數字等我一直在嘗試一些正則表達式,但它沒有成功。這是最後一個:

/#{(\w+)}({([\ a-zA-Z0-9*])})*/U 

在此先感謝!

編輯:就像@stema的建議,我改變了我的正則表達式這一個:

/#\{(\w+)\}(\{([^}]*)\})*/ 

我避免了Ungreedy標誌,因爲它不是在所有:)幫助表達。然而,結果並不像我需要儘可能多的:

array(4) { 
    [0]=> 
    string(42) "#{text1}{text with spaces}{numbers}{text2}" 
    [1]=> 
    string(5) "text1" 
    [2]=> 
    string(7) "{text2}" 
    [3]=> 
    string(5) "text2" 
} 

看來,其間的參數不被解析(看起來怪我)。

+0

它失敗了:當試圖解析最後一個例子(有4個塊)時,我得到了這些匹配:#{text1}和text1 – Korcholis

+0

看起來你只是在第二個括號內有一個字符'{([\ a- zA-Z0-9 *])}'應該像'{([\ a-zA-Z0-9 *] +)}' – devsnd

+0

我更新了我的答案。 – stema

回答

5

主要的問題,我看到的是量詞是放錯了地方

/#{(\w+)}({([\ a-zA-Z0-9*])})*/U 
         ^

應該是字符類

/#{(\w+)}({([\ a-zA-Z0-9]*)})*/U 

外部。如果在下面的括號中的內容可以是任何東西比你能做到這一點

/#\{(\w+)\}(\{([^}]*)\})*/U 

[^}]是一個否定的字符類,它匹配anyt興奮,但最後的大括號。

我也逃過了大括號,因爲它們作爲量詞的一部分有着特殊的含義。有些語言不會形成這樣一個量詞,但是爲了清晰起見,當它們應該匹配時,最好總是逃避它們。

更新:

你可以讓你的羣組中的非捕獲組,因爲你似乎並不需要它

/#\{(\w+)\}(?:\{([^}]*)\})*/ 

這應該給你這個結果

array(4) { 
    [0]=> 
    string(42) "#{text1}{text with spaces}{numbers}{text2}" 
    [1]=> 
    string(5) "text1" 
    [2]=> 
    string(5) "text2" 
} 

但是您將只會得到重複組的最後一場匹配,因爲每個匹配都存儲在array[2]。第二場比賽將覆蓋第一個,第二個第二個...

你可以做的是使用正則表達式進行格式驗證,然後做一個分割例如像這樣

$in = "#{text1}{text with spaces}{numbers}{text2}"; 
$result = preg_split('/}{|#{|}/', $in, -1, PREG_SPLIT_NO_EMPTY); 
+0

+1。我也會擺脫大括號。並非所有的正則表達式引擎都足夠聰明,可以從上下文中推斷出它們在這裏不是一個量詞,並且會在編譯時產生錯誤。 –

+0

謝謝Tim,我將它添加到我的答案中。 – stema

+0

您可以使用'+'而不是'*'來避免第一個塊。 – dresende

2

繼STEMA的答案,我會建議

  1. 與您正則表達式
  2. 驗證字符串,你不能使用捕獲組用於這個目的,我會帶出領先#{和尾隨}然後split這個正則表達式上的字符串}{

這應該會給你一個所有匹配的數組。

+0

非常感謝,@Joanna!因爲這個好主意,我也給你+1。不過,@ stema的更完整,所以我必須接受他。 – Korcholis