質問
正規表現のヘルプを少し探しています。 " foo "の文字列に一致する式を設計したいまたは" bar &quot ;、ただし両方は" foo " AND" bar "
次のような場合...
/((foo)|(bar))/
" foobar "と一致します。私が探しているものではありません。したがって、1つの用語または他の用語が存在する場合にのみ正規表現を一致させるにはどうすればよいですか?
ありがとう!
解決
単一の正規表現でこれを行うことができますが、読みやすくするために次のようなことを行うことをお勧めします...
(/foo/ and not /bar/) || (/bar/ and not /foo/)
他のヒント
正規表現言語でサポートされている場合は、ネガティブルックアラウンドを使用します。
(?<!foo|bar)(foo|bar)(?!foo|bar)
これは&quot; foo&quot;と一致しますまたは「バー」 &quot; foo&quot;の直前または直後ではありません。または「バー」、これはあなたが望んでいたものだと思います。
照合しようとしている文字列に他のトークンを含めることができるかどうかは、質問または例から明らかではありません:&quot; foocuzbar&quot;。その場合、このパターンは機能しません。
テストケースの結果は次のとおりです(&quot; true&quot;は入力でパターンが見つかったことを意味します):
foo: true
bar: true
foofoo: false
barfoo: false
foobarfoo: false
barbar: false
barfoofoo: false
これは「foo」と「bar」を取りますが、「foobar」と「blafoo」と「blabar」は取りません:
/^(foo|bar)$/
^ = mark start of string (or line)
$ = mark end of string (or line)
これは、「foo」と「bar」と「foo bar」と「bar-foo」を取りますが、「foobar」と「blafoo」と「blabar」は取りません:
/\b(foo|bar)\b/
\b = mark word boundry
&quot; foo&quot;以外のコンテンツに関する動作を指定していません。および「バー」または、一方が存在しない場合の一方の繰り返し。例:&quot; foo d&quot;または&quot; barbar ian&quot;一致しますか?
いずれかの&quot; foo&quot;のインスタンスを1つだけ含む文字列に一致させたいと仮定します。または「バー」、ただし両方ではなく、同じインスタンスの複数のインスタンスではなく、文字列内の他のものに関係なく(つまり、「食べ物」が一致し、「野b人」が一致しない)、正規表現を使用できます見つかった一致の数を返し、一致が1つだけ見つかった場合にのみ成功したと見なします。例:Perl:
@matches = ($value =~ /(foo|bar)/g) # @matches now hold all foos or bars present
if (scalar @matches == 1) { # exactly one match found
...
}
同じターゲットの複数の繰り返しが許可されている場合(つまり、「野b人」の一致)、この同じ一般的なアプローチを使用して、一致のリストを歩いて、一致がすべて同じテキストの繰り返しであるか、他のオプションも存在する場合。
もしあなたが本当の排他的またはを望むなら、私は正規表現ではなくコードでそれをするでしょう。 Perlの場合:
/foo/ xor /bar/
ただし、コメント:
一致:&quot; foo&quot;、&quot; bar&quot;不一致: &quot; foofoo&quot; &quot; barfoo&quot; &quot; foobarfoo&quot; &quot; barbar&quot; &quot; barfoofoo&quot;
は、排他的ORを探していないことを示します。あなたは実際に意味する
&quot; / foo | bar /
は1回だけ一致しますか?&quot;
my $matches = 0;
while (/foo|bar/g) {
last if ++$matches > 1;
}
my $ok = ($matches == 1)
これは遅いエントリですが、見ている人を助けるためだけのものです:
(/b(?:(?:(?!foo)bar)|(?:(?!bar)foo))/b)
このようなものを使用します。単語の周囲のスペースをチェックするだけですが、 \ w
を使用する場合は、 \ b
または \ B
を使用して境界をチェックできます。 。これは&quot;と一致しますfoo&quot;または&quot; bar&quot;なので、万が一に備えて空白も置き換える必要があります。 (何かを交換すると仮定します。)
/\s((foo)|(bar))\s/
これを単一の正規表現で実行できるとは思わない。境界線は、照合対象に応じて機能する場合と機能しない場合があります。
各正規表現と個別に照合し、結果に対してXORを実行します。
foo = re.search("foo", str) != None
bar = re.search("bar", str) != None
if foo ^ bar:
# do someting...
Regex Coachで試したのは:
x foo y
x bar y
x foobar y
g
オプションをオンにすると、一致するたびに再度検索されるため、実際には3つの単語すべてに一致します。
この動作が望ましくない場合は、式を固定することができます。たとえば、単語の境界でのみ一致します。
\b(foo|bar)\b
問題に関するより多くのコンテキスト(データがどのように見えるか)を与えると、より良い答えが得られる可能性があります。
\b(foo)\b|\b(bar)\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"