2

ここでの後方参照の問題は何だろうか:

preg_match_all('/__\((\'|")([^\1]+)\1/', "__('match this') . 'not this'", $matches);

__('') の間の文字列に一致することが期待されますが、実際には次のように返されます。

match this') . 'not this

何か案は?

4

4 に答える 4

6

文字クラスは正確に 1 文字に一致し、後方参照は任意の数の文字に一致する可能性があるため、文字クラス内で後方参照を使用することはできません。

あなたがやろうとしていることは、否定された文字クラスではなく、否定的な先読みが必要です:

preg_match_all('/__\(([\'"])(?:(?!\1).)+\1\)/',
    "__('match this') . 'not this'", $matches);

また、代替\'|"を文字クラスに変更しました。[\'"]これは、はるかに効率的であるためです。また、外側の括弧をエスケープして、リテラルの括弧と一致させました。


編集:その「より効率的な」発言を拡張する必要があると思います。この点を示すために Friedl が使用した例を取り上げ、RegexBuddy でテストしました。

ターゲット テキストabababdedfgに適用され
^[a-g]+$、3 ステップ後に成功を報告しますが、
^(?:a|b|c|d|e|f|g)+$55 ステップかかります。

そして、それは成功した試合のためです。試着するとabababdedfz
^[a-g]+$21ステップ後に失敗が報告されます。
^(?:a|b|c|d|e|f|g)+$99歩かかります。

この特定のケースでは、パフォーマンスへの影響はごくわずかであるため、言及する価値さえありません。同じものに一致する文字クラスと代替案のどちらかを選択する場合は、ほとんどの場合、文字クラスを使用する必要があります。経験則です。

于 2011-05-18T21:14:24.680 に答える
2

かっこのバランスが取れていないというエラー メッセージが表示されなかったことに驚いています。

 /
   __
   (
       (\'|")
       ([^\1]+)
       \1
 /

これ[^\1]は、キャプチャ バッファ 1 の内容を取得せず、文字
クラスに配置します。「1」以外のすべての文字と同じです。

これを試して:

/__\(('|").*?\1\).*/

内側のキャプチャ括弧を追加して、引用符の間の内容をキャプチャすることができます:
/__\(('|")(.*?)\1\).*/

編集: 内側の区切り文字が許可されていない場合は、Qtax regex を使用してください。
貪欲で('|").*?\1はありませんが、後続のアンカーまですべて一致するためです。この場合__('all'this'will"match')、次のように使用すること('[^']*'|"[^"]*) をお勧めします

于 2011-05-18T20:34:32.183 に答える
1

次のようなものを使用できます。 /__\(("[^"]+"|'[^']+')\)/

于 2011-05-18T20:31:09.353 に答える
-1

正規表現を非貪欲にします:

preg_match_all('/__((\'|")([^\1]+)\1/U', "__('match this') . 'not this'", $matches)
于 2011-05-18T20:16:39.127 に答える