2011-07-29 83 views
0

我已經從朋友(現在休假的人)得到了一些幫助,但是我在搜索和替換preg_replace時遇到了問題。我不知道爲什麼,但是它會錯誤地替換字符串,這會對應該替換的下一個字符串造成影響。preg_replace替換不正確

這基本上在模板類中處理模板中的'if'和'else'查詢。

function if_statement($a, $b, $if, $type, $else = NULL){ 
    if($type == "1" && is_numeric($a) && is_numeric($b)){ 
     $statement = ($a === $b) ? $if : $else; 
    } else if($type == "1"){ 
     $statement = ($a == $b) ? $if : $else; 
    } else if($type == "2"){ 
     $statement = ($a != $b) ? $if : $else; 
    } 
    return stripslashes($statement); 
} 

$output = file_get_contents("template.tpl"); 

$replace = array(
    '#\<if:"\'(.*?)\' == \'(.*?)\'"\>(.*?)\<else\>(.*?)\<\/endif\>#sei', 
    '#\<if:"\'(.*?)\' == \'(.*?)\'"\>(.*?)\<\/endif\>#sei' 
); 
$functions = array(
    "if_statement('\\1', '\\2', '\\3', '1', '\\4')", 
    "if_statement('\\1', '\\2', '\\3', '1')" 
); 
$output = preg_replace($replace, $functions, $output); 
echo $output; 

模板:

<HTML> 
    <head> 
    <meta http-equiv="content-type" content="application/xhtml+xml; charset=UTF-8" /> 
    <title>Site Title</title> 
    <link rel="stylesheet" type="text/css" media="screen" href="common.css" /> 
    <if:"'{ISADMIN}' == '1'"> 
     <link rel="stylesheet" href="admin-bar.css" type="text/css" media="all" /> 
    </endif> 
</head> 
<body> 
    <if:"'{TODAY}' == 'Monday'">Today is Monday<else>Today is not Monday</endif> 
    <if:"'1' == '2'">1 equals 2!<else>1 doesn't equal 2</endif> 
</body> 
</html> 

當電流輸出將低於:

<HTML> 
    <head> 
    <meta http-equiv="content-type" content="application/xhtml+xml; charset=UTF-8" /> 
    <title>Site Title</title> 
    <link rel="stylesheet" type="text/css" media="screen" href="common.css" /> 

     <link rel="stylesheet" href="admin-bar.css" type="text/css" media="all" /> 
    **</endif>** 
</head> 
<body> 
    **<if:"'{TODAY}' == 'Monday'">**Today is Monday 
    1 doesn't equal 2 
</body> 
</html> 

在上文中,粗體/阿斯特里克斯makred零件不應該有對輸出,今天也不是星期一。雖然管理員已登錄,但admin-bar.css文件已被正確包含,但由於某種原因未收到</endif>標籤 - 事實上,它看起來像是在<else>標籤之後,而不是在下一個語句中......在其他單詞preg_replace匹配了一個不正確的東西!因此並沒有在第二個<if>聲明中看到。

{BRACKET}標籤是否被正確替換 - 我甚至手動將數據導入語句(只是爲了檢查),所以他們都沒有問題......

我不知道爲什麼,但我preg_replace沒有找到正確的序列來替換和採取行動。如果任何人都可以放下一雙新的眼睛/伸出一隻手,我會很感激。

謝謝!

回答

3

樣本中的第一個<if>沒有<else>子句。因此,當<if:"'(.*?)' == '(.*?)'">(.*?)<else>(.*?)</endif>(其中<else>不可選)適用於它,它匹配這一切:

<if:"'{ISADMIN}' == '1'"> 
     <link rel="stylesheet" href="admin-bar.css" type="text/css" media="all" /> 
    </endif> 
</head> 
<body> 
    <if:"'{TODAY}' == 'Monday'">Today is Monday<else>Today is not Monday</endif> 

在那場比賽,小組$3

 <link rel="stylesheet" href="admin-bar.css" type="text/css" media="all" /> 
    </endif> 
</head> 
<body> 
    <if:"'{TODAY}' == 'Monday'">Today is Monday 

您可避免通過禁止正則表達式使用向前斷言跨越一個</endif>

'%<if:\s*"\'([^\']*)\' == \'([^\']*)\'">((?:(?!<else>|</endif>).)*)<else>((?:(?!</endif).)*)</endif>%si' 

,或者在評價形式(以及可能的更helpfu l當一個程序員再次變爲「去度假」):

'%<if:\s*"\'  # Match <if:(optional space)"\' 
    ([^\']*)  # Match 0 or more non-quote characters, capture group 1 
    \'\s==\s\' # Match \' == \' 
    ([^\']*)  # Match 0 or more non-quote characters, capture group 2 
    \'">   # Match \'"> 
    (   # Capture into group 3: 
    (?:   # The following group... 
     (?!  # only if we\'re not right before... 
     <else> # <else> 
     |   # or 
     </endif> # </endif> 
    )   # (End of lookahead assertion) 
     .   # Match any character 
    )*   # Repeat as necessary 
    )   # End of capturing group 3 
    <else>  # Match <else> 
    (   # Same construction as above, group 4 
    (?: 
     (?! 
     </endif> # this time only looking for </endif> 
    ) 
     . 
    )* 
    ) 
    </endif>  # and finally match </endif> 
    %esix' 

第二個正則表達式也應該改進:

'%<if:\s*"\'  # Match <if:(optional space)"\' 
    ([^\']*)  # Match 0 or more non-quote characters, capture group 1 
    \'\s==\s\' # Match \' == \' 
    ([^\']*)  # Match 0 or more non-quote characters, capture group 2 
    \'">   # Match \'"> 
    (   # Capture into group 3: 
    (?: 
     (?! 
     </endif> # Any text until </endif> 
    ) 
     . 
    )* 
    ) 
    </endif>  # and finally match </endif> 
    %esix' 

而且,這些正則表達式應該會更快,因爲他們更加清晰地明確什麼可以和什麼無法匹配,從而避免了很多回溯。

+0

感謝您的幫助和解釋Tim!是否有可能在最初的' MrJ

+0

當然,我編輯了我的答案。 –