少しの正規表現のヘルプを探しています。「 foo」または「bar 」の文字列に一致する式を設計したいが、 「 foo」と「bar」の両方には一致しない
私が何かをするなら...
/((foo)|(bar))/
「 foobar 」にマッチします。私が探しているものではありません。では、どちらかの用語が存在する場合にのみ正規表現を一致させるにはどうすればよいですか?
ありがとう!
正規表現言語がそれをサポートしている場合は、ネガティブルックアラウンドを使用してください:
(?<!foo|bar)(foo|bar)(?!foo|bar)
これは、「foo」または「bar」の直前または直後にない「foo」または「bar」と一致します。これは、あなたが望んでいたことだと思います。
一致させようとしている文字列に他のトークン「foocuzbar」が含まれている可能性があるかどうかは、質問や例からは明らかではありません。その場合、このパターンは機能しません。
テストケースの結果は次のとおりです(「true」は、パターンが入力で見つかったことを意味します)。
foo: true
bar: true
foofoo: false
barfoo: false
foobarfoo: false
barbar: false
barfoofoo: false
単一の正規表現でこれを行うことができますが、読みやすくするために次のようなことをお勧めします...
(/foo/ and not /bar/) || (/bar/ and not /foo/)
「foo」と「bar」以外のコンテンツ、または一方が存在しない場合の一方の繰り返しに関する動作を指定していません。たとえば、 「 food」または「barbarian」は一致する必要がありますか?
「foo」または「bar」のいずれかのインスタンスを1つだけ含むが、両方ではなく、同じインスタンスの複数のインスタンスを含まない文字列を、文字列内の他のインスタンスに関係なく一致させたいと仮定します(つまり、「food」は「野蛮人」は一致しません)、見つかった一致の数を返す正規表現を使用して、一致が1つだけ見つかった場合にのみ成功したと見なすことができます。例:Perlの場合:
@matches = ($value =~ /(foo|bar)/g) # @matches now hold all foos or bars present
if (scalar @matches == 1) { # exactly one match found
...
}
同じターゲットの複数の繰り返しが許可されている場合(つまり、「野蛮な」一致)、一致のリストを調べて、一致がすべて同じテキストの繰り返しであるかどうか、または他のオプションがあるかどうかを確認することで、この同じ一般的なアプローチを使用できます。も存在します。
真の排他的 OR が必要な場合は、正規表現ではなくコードでそれを行います。パールでは:
/foo/ xor /bar/
しかし、あなたのコメント:
一致: "foo"、"bar" 非一致: "foofoo" "barfoo" "foobarfoo" "barbar" "barfoofoo"
排他的な or を探しているわけではないことを示します。あなたは実際には「/foo|bar/
正確に1回一致しますか?」という意味です。
my $matches = 0;
while (/foo|bar/g) {
last if ++$matches > 1;
}
my $ok = ($matches == 1)
これが遅いエントリであることは承知していますが、探している可能性のある他の人を助けるために:
(/b(?:(?:(?!foo)bar)|(?:(?!bar)foo))/b)
単語の境界を使用して、単一の単語を取得できます...
me@home ~
$ echo "Where is my bar of soap?" | egrep "\bfoo\b|\bbar\b"
Where is my bar of soap?
me@home ~
$ echo "What the foo happened here?" | egrep "\bfoo\b|\bbar\b"
What the foo happened here?
me@home ~
$ echo "Boy, that sure is foobar\!" | egrep "\bfoo\b|\bbar\b"
\b(foo)\b|\b(bar)\b
そして、最初のキャプチャ グループのみを使用します。
私はこのようなものを使用します。単語の周りのスペースをチェックするだけですが、 を使用する場合は\b
または\B
を使用して境界線をチェックできます\w
。これは「 foo 」または「 bar 」に一致するため、念のために空白も置き換える必要があります。(何かを交換していると仮定します。)
/\s((foo)|(bar))\s/
これは単一の正規表現ではできないと思います。また、境界は、照合対象に応じて機能する場合と機能しない場合があります。
各正規表現に対して個別に照合し、結果に対して XOR を実行します。
foo = re.search("foo", str) != None
bar = re.search("bar", str) != None
if foo ^ bar:
# do someting...
私は正規表現コーチで試しました:
x foo y
x bar y
x foobar y
このオプションをチェックするg
と、一致するたびに再度検索されるため、実際に 3 つの単語すべてに一致します。
この動作が望ましくない場合は、式を固定できます。たとえば、単語の境界でのみ一致します。
\b(foo|bar)\b
問題 (データがどのように見えるか) についてより多くのコンテキストを提供すると、より良い答えが得られる可能性があります。