空の可能性のある後方参照を使用する 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);
?>