2010-04-15 53 views
3

我有一個PHP正則表達式,一直運行得很好,可以解析一些古老的客戶端模板,直到最近我們發現模板表達式中包含一個轉義問號(\?)。我用我的正常表情fu不夠強,用我的微弱麪條來包裹負面看法或者一些techno-mumbo-jumbo,所以,正確方向的提示或要點將不勝感激。使用正則表達式來匹配?但不是?

我的PHP:

preg_match_all("/\{\{IF (.*)\?(.*):(.*)\}\}/U", $template, $m, PREG_SET_ORDER); 

好吧,我有點不知所措,當我張貼了這個問題。讓我把它放在適當的背景下。

模板的代碼如下所示:

{{IF VAR?"SHOW: THIS?":"SHOW {{ELSE}}"}} 

哪些應該被解析爲:

if ($template[$var]) { 
echo "SHOW: THIS?"; 
} else { 
echo "SHOW ".$template['ELSE']; 
} 

我目前幾乎與我的功能實現這一點,但並不完全。這是函數:

preg_match_all("/\{\{IF ((?:[^\\?]|\\.)*)\?((?:[^\\:]|\\.)*):(.*)\}\}[^<\/]/", $template, $m, PREG_SET_ORDER); 
if (count($m)) { 
foreach ($m as $o) { 
    if (preg_match("/(.*)\s+(==|!=)\s+(.*)/", $o[1], $x)) { 
    if (preg_match("/^\"(.*)\"/", $x[1], $cx)) $e1 = $cx[1]; 
    else $e1 = is_numeric($x[1])?$x[1]:$data[$x[1]]; 
    if (preg_match("/^\"(.*)\"/", $x[3], $cx)) $e2 = $cx[1]; 
    else $e2 = is_numeric($x[3])?$x[3]:$data[$x[3]]; 
    if (preg_match("/^\"(.*)\"/", $o[2], $ox)) $er[0] = $ox[1]; 
    else $er[0] = addslashes(htmlspecialchars($data[$o[2]])); 
    if (preg_match("/^\"(.*)\"/", $o[3], $ox)) $er[1] = $ox[1]; 
    else $er[1] = addslashes(htmlspecialchars($data[$o[3]])); 
    $eval = "\$od = (\"$e1\" $x[2] \"$e2\")?\"$er[0]\":\"$er[1]\";"; 
    eval($eval); 
    } else { 
    $od = $data[$o[1]]?$o[2]:$o[3]; 
    if (preg_match("/^\"(.*)\"/", $od, $x)) $od = $x[1]; 
    else $od = $data[$od]; 
    } 
    $template = str_replace($o[0], $od, $template); 
} 
} 

if (is_array($data)) 
foreach ($data as $k => $v) $template = str_replace('{{'.$k.'}}', $v, $template); 
return $template; 
+0

此外,我正在尋找適用於冒號(:)的解決方案。 – Millions 2010-04-15 01:20:13

+0

相關問號在哪裏出現? – cletus 2010-04-15 01:22:36

+0

好的,當我發佈這個問題時,我有點不知所措。讓我把它放在適當的背景下。 模板代碼看起來是這樣的: {{IF VAR 「顯示:此?」: 「SHOW {{ELSE}}」}} 這應該是: 如果($模板[$ VAR]){ \t \t回聲「SHOW:THIS?」; \t} else { \t \t echo「SHOW」。$ template ['THIS']; \t} 我目前幾乎是用我的功能實現這個功能,但並不完全。這是一個函數:http://snipplr.com/view/31855/a-ninja-funerals/ – Millions 2010-04-15 02:25:53

回答

1

爲什麼不

(.*)[^\\]\?(.*) 
+0

這不匹配以?開頭的行嗎?雖然。你必須爲此添加其他內容。這是你需要處理的情況嗎? – Chris 2010-04-15 01:16:41

2

你需要改變你的(.*)地區—它不再是真實的,你想匹配的任何序列。相反,您要匹配一系列非轉義字符或轉義序列:((?:[^\\]|\\.)*)這將匹配包含反斜槓轉義的任何字符串。我認爲你可以通過指定不希望匹配問號或冒號的方式來提高性能;如果你這樣做了,你最終會得到正則表達式/\{\{IF ((?:[^\\?]|\\.)*)\?((?:[^\\:]|\\.)*):(.*)\}\}/。雖然這看起來很討厭,但我只是用我從上面得到的結構代替了你的(.*);這非常簡單。

+0

Gooder ...溫暖。我希望我第一次更好地闡述我的問題。 – Millions 2010-04-15 02:30:16

1

這是什麼工作。感謝@absz提供了一個正確的方向。

preg_match_all("/\{\{IF ([^\"\\]]*(\\.[^\"\\]]*)*)\?((?:[^\\:]|\\.)*):(.*)}\}/", $template, $m, PREG_SET_ORDER); 
+0

很高興我能幫到你。 – 2010-04-17 17:02:38