次の文字列を想定します。
aaa bbb ccc
bbb aaa ccc
文字列の先頭にない限り、aaa
に一致させたい。私は次のようなことをしてそれを打ち消そうとしています:
[^^]aaa
しかし、私はこれが正しいとは思いません。 preg_replace
を使用します。
背後を見て、最初になっていないことを確認できます。 (?<!^)aaa
私がGoogle検索経由でここに来て、後読みを使用していないソリューションに興味を持っただったので、ここに2セントがあります。
[^^]aaa
パターンは、^
および3 a
s anywhere 以外の文字に一致します。 [^...]
は negated character class であり、^
は特殊文字とは見なされません。 ^
の直後にある最初の[
は否定を示すため特別であり、2番目は単なるリテラルキャレット記号であることに注意してください。
したがって、^
を[...]
の中に入れて、文字列の開始を示すことはできません。
解決策は、否定的なルックアラウンドを使用することです。これらの2つは同等にうまく機能します。
(?<!^)aaa
そして先読み:
(?!^)aaa
先読みも機能するのはなぜですか? Lookarounds はゼロ幅のアサーションであり、アンカーもゼロ幅です-それらはテキストを消費しません。文字通り、(?<!^)
は、現在の場所のすぐ左側に文字列の開始位置がないかどうかをチェックし、(?!^)
は、現在の場所のすぐ右側に文字列開始位置がないかどうかをチェックします。同じ locations がチェックされているため、どちらも正常に機能します。
後読みを使用したくない場合は、次の正規表現を使用します。
/.(aaa)/
そしてmatched group # 1
。
この状況は、ルックアラウンドが_\K
_よりも優れているのを目にしたのは初めてです。面白い。
通常、キャプチャグループとルックアラウンドには追加の手順が必要です。ただし、このタスクの性質上、正規表現エンジンはaaa
を検索して文字列をより速くナビゲートし、文字列アンカーの開始を探すことができます。
比較のためにいくつかの_\K
_パターンを追加します。
先頭の文字が改行文字(_.
_は通常一致しない)になる可能性がある場合は、s
パターン修飾子を使用しています。私が提起されるかもしれない周辺の問題に先制的に対処するために、この考慮事項を追加するつもりでした。
繰り返しますが、これは私が_\K
_を扱った他のすべての正規表現のケースで他の手法を打ち負かしているため、啓発的なシナリオです。
歩数比較マトリックス:
_ | `~.\Kaaa~s` | `~.+?\Kaaa~s` | `(?<!^)aaa` | `(?!^)aaa` | `.(aaa)` |
--------------|-------------|---------------|-------------|------------|----------|
`aaa bbb ccc` | 12 steps | 67 steps | 8 steps | 8 steps | 16 steps |
--------------|-------------|---------------|-------------|------------|----------|
`bbb aaa ccc` | 15 steps | 12 steps | 6 steps | 6 steps | 12 steps |
_
要点は次のとおりです。パターンの効率について学ぶには、パターンをregex101.comに吐き出して、ステップ数を比較します。
また、あなたが探しているknow正確にどの部分文字列を探していて、正規表現パターンが必要ない場合は、strpos()
をベストプラクティスの問題として使用する必要があります(そして戻り値が_> 0
_)であることを確認します。
私は、Googleスプレッドシートで使用されるre2エンジンのソリューションを見るためにここに来ましたが、これはルックアラウンドをサポートしていません。しかし、ここでの答えは私に次のものを使うという考えを与えました。なぜ私が捕獲されたグループに置き換えなければならないのか分かりませんが、とにかくそれはうまくいきます。
aaa bbb ccc
bbb aaa ccc
([^^])aaa
置き換え:
$1zzz
再利用:
aaa bbb ccc
bbb zzz ccc