1

空の可能性のある後方参照を使用する PHP の正規表現に問題があります。http://www.regular-expressions.info/brackets.htmlで説明されているように機能することを望んでいました:

特定の一致試行で後方参照が使用されなかった場合 (疑問符によって最初の後方参照がオプションになった最初の例など)、単純に空になります。正規表現で空の後方参照を使用してもまったく問題ありません。それは単に無に置き換えられます。

ただし、PHP は少し異なるようです... http://php.net/manual/en/regexp.reference.back-references.phpとは異なります。

サブパターンが特定の一致で実際に使用されていない場合、それへの後方参照は常に失敗します。

簡単な例として、次の 2 つのことをこの正規表現と照合します。

  • {何か} ... {/何か}
  • {something:else} ... {/something:else}

「何か」は前もってわかっており、「その他」は何でもかまいません (または何もありません)。

だから私は次の正規表現を試しました(「else」は簡単にするためにハードコードされています):

preg_match("/\{(something(:else)?)\}(.*?)\{\/something\\2\}/is", $data, $matches)

残念ながら if (:else)? \2 後方参照は失敗します。\2 をオプション (\2?) にすると、{something} ... {something:else} に一致する可能性がありますが、これは良くありません。

正規表現の制限 (悪名高い「正規表現ではなくパーサーが必要」) に遭遇しましたか、それとも修正可能ですか?

テストプログラム:

<?php
    $data = "{something} ... {/something}
             {something:else} ... {/something:else}
             {something:else} ... {/something}";

    // won't match {something} ... {/something}
    preg_match_all("/\{(something(:else)?)\}(.*?)\{\/something\\2\}/is", $data, $matches);
    print_r($matches);

    // change \\2 to \\2? and it matches too much
    preg_match_all("/\{(something(:else)?)\}(.*?)\{\/something\\2?\}/is", $data, $matches);
    print_r($matches);
?>
4

3 に答える 3

2

さて、なぜ置き換えませんか?または?

変化する

"/\{(something(:else)?)\}(.*?)\{\/something\\2\}/is"

"/\{(something(:else|))\}(.*?)\{\/something\\2\}/is"

そうすれば、参照は常にキャプチャされますが、空になることがあります(これは問題ありません)...

于 2010-08-11T14:04:08.593 に答える
1

\2 の代わりに単に \1 を使用しないのはなぜですか?

preg_match_all("/\{(something(:else)?)\}(.*?)\{\/\\1\}/is", $data, $matches);

「パーサーが必要」の問題に関しては、ネストされた構造を解析するためにパーサーが必要になります/必要になります。

于 2010-08-11T14:09:50.873 に答える