2012-02-17 13 views
2

私は例えば、タグのプロパティのものを除いて一致する引用符をエスケープしたい:エスケープマッチング引用符

入力:

xyz <test foo='123 abc' bar="def 456"> f00 'escape me' b4r "me too" but not this </tEsT> blah 'escape " me' 

予想される出力:

xyz <test foo='123 abc' bar="def 456"> f00 \'escape me\' b4r \"me too\" but not this </tEsT> blah \'escape " me\' 

私は、次のしています正規表現:

$result = preg_replace('/(([\'"])((\\\2|.)*?)\2)/', "\\\\$2$3\\\\$2", $input); 
xyz <test foo=\'123 abc\' bar=\"def 456\"> f00 \'escape me\' b4r \"me too\" but not this </tEsT> blah \'escape " me\' 

を今、私は前に等号を持っている引用符をマッチングスキップするの背後にある正規表現ゼロ幅の負の外観を使用したい:

$result = preg_replace('/((?<=[^=])([\'"])((\\\2|.)*?)\2)/', "\\\\$2$3\\\\$2", $input); 

が、期待通りの結果がまだない返し:

xyz <test foo='123 abc\' bar="def 456"> f00 \'escape me\' b4r "me too" but not this </tEsT> blah \'escape " me' 

あなたは私だけではなく、最初の引用符をスキップの私は全体の不要なブロックをスキップすることができますどのようにアドバイス(=「何とか何とか何とか」)をお願いできますか?

+0

正規表現ではこれを行わないでください。あなたはそれを後悔します。 – Jon

答えて

2

コンテキストを確立するために後方を見るのではなく、楽しみにしています。通常ははるかに簡単です。

$result = preg_replace('/([\'"])(?![^<>]*>)((?:(?!\1).)*)\1/', 
         '\\\\$1$2\\\\$1', 
         $subject); 
(['"])   # capture the open quote 
(?![^<>]*>)  # make sure it's not inside a tag 
(    # capture everything up to the next quote 
    (?:    # ...after testing each character to 
    (?!\1|[<>]). # ...to be sure it's not the opening quote 
)*    # ...or an angle bracket 
) 
\1    # match another quote of the same type as the first one 

私は属性値内の任意の山括弧がないだろうと仮定しています。

+0

それは私のために完全に動作します!詳細な説明をいただきありがとうございます。正規表現をどこで学んだのですか? – Artur

+0

@Artur:主に[Mastering Regular Expressions](http://shop.oreilly.com/product/9780596528126.do)を読んで、練習し、このようなフォーラムでぶらついています。 :D –

1

もう1つです。

$str = "xyz <test foo='123 abc' bar=\"def 456\"> f00 'escape me' b4r \"me too\" but not this <br/> <br/></tEsT> blah 'escape \" me'"; 

$str_escaped = preg_replace_callback('/(?<!\<)[^<>]+(?![^<]*\>)/','escape_quotes',$str); 
// check all the strings outside every possible tag 
// and replace each by the return value of the function below 

function escape_quotes($str) { 
    if (is_array($str)) $str = $str[0]; 
    return preg_replace('/(?<!\\\)(\'|")/','\\\$1',$str); 
    // escape all the non-escaped single and double quotes 
    // and return the escaped block 
} 
+0

これはすべての条件で動作しているかどうか確認してもらえますか? ** <** and **> **の記号は、タグを囲む記号以外の記号(それぞれ '< 'と' > ')にエスケープされていると仮定しています。 – inhan