引用符の外側で発生するパターンをチェックするだけの場合、解決策は簡単で、先読みでゲームをプレイする必要はありません。(複雑な先読みは、病的に遅い正規表現を生成するための常に良い方法です。) 一致の前に偶数の引用符があることを知ることは、その後に偶数の引用符があることを知ることと同じくらい有効であり、前者は潜在的な一致ごとに文字列全体を投機的に一致させる必要がないため、チェックがはるかに簡単かつ高速になります。ただし、貪欲でない繰り返しが必要です。そうしないと、最初の一致ではなく、最後の可能な一致が見つかります。
簡単な例を次に示します。
^(?:[^']*'[^']*')*?[^']*?foo\.bar
|-paired 's| |----------The pattern.
|-shortest match-|
|----|
no quotes
{}
しかし、あなたは実際には何らかの方法で特別にしたいとも思っています。あなたはそれについてはっきりしていないように見えるので、私はただ推測しています。ブラケットがネストできる場合、正規表現は適切ではありません。(「正規表現はカウントできません。」)
更新された要件(コメント内)に基づいて、
- 引用符で中括弧を隠す
- 中括弧は引用符を隠します
- 中かっこと引用符はどちらもターゲットを隠します。と
- ブレースはネストしません
解決策は、私が上で提案したものと大差ありません。{[^}]*}
を初期パターンに追加するだけです。1 つの可能性を次に示します。
^(?:[^'{]*(?:'[^']*'|{[^}]*}))*?[^'{]*?foo\.bar
これは(あまり良くない)テストです。-o オプションを指定すると、grep は一致した部分を表示するため、各一致が終了する場所を確認できます。
$ grep -oP "^(?:[^'{]*(?:'[^']*'|{[^}]*}))*?[^'{]*?foo\.bar" <<\EOF
The target string is foo.bar and we should match the first foo.bar
'foo.bar' does not match but foo.bar does
Also, {foo.bar} doesn{'}t match, 'foo.bar' doesn{'}t match, {'foo.bar} doesn{'}t match, but foo.bar does
Note that {braces don't {nest so the end is here} and foo.bar matches}
EOF
これは以下を生成します:
The target string is foo.bar
'foo.bar' does not match but foo.bar
Also, {foo.bar} doesn{'}t match, 'foo.bar' doesn{'}t match, {'foo.bar} doesn{'}t match, but foo.bar
Note that {braces don't {nest so the end is here} and foo.bar