2011-07-29 11 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>タグの後になっているようですwords、preg_replaceが間違ったものにマッチしました!したがって、2番目の<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 

ですコメントフォーム(そしておそらくよりhelpfuで

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

または、:先読みアサーションを使用して</endif>を跨ぎますプログラマは再び)「離れて休日に」行くリットルは:

'%<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

確かに、私は私の答えを編集しました。 –

関連する問題