正規表現-特定のパターン以外のすべてに一致させる方法


171

特定のパターンに一致しない文字列に一致するように正規表現を作成するにはどうすればよいですか?(Aおよび〜B)パターンに一致する必要がある状況に直面しています。


PCREはこれに最適です。一致する正規表現パターンを参照してください。findstrここではすべての回答がタグに対して有効ではないため、タグを削除しました。
WiktorStribiżew

回答:


192

先読みアサーションを使用できます。

(?!999)\d{3}

この例は、以外の3桁と一致し999ます。


ただし、この機能を使用して正規表現を実装していない場合(「正規表現フレーバーの比較」を参照)、基本的な機能を備えた正規表現を自分で作成する必要があります。

基本的な構文のみと互換性のある正規表現は次のとおりです。

[0-8]\d\d|\d[0-8]\d|\d\d[0-8]

これは、3桁でないシーケンスにも一致します999


1
先読みは標準の正規表現構文ではなく、Perlの拡張機能であり、Perl、PCRE(Perl互換のRegEx)、またはその他の非標準の実装でのみ機能します
Juliano

10
それは標準ではないかもしれませんが、ほとんどの現代の言語はそれをサポートしていませんか?最近、どの言語で先読みがサポートされていませんか?
ブライアンオークリー

1
それは本当だ。ただし、ほとんどの正規表現フレーバーはこの機能をサポートしています(< regular-expressions.info/refflavors.html>を参照)。
ガンボ

1
最後の正規表現も
009、019

1
標準Lex for CはPCREを使用しません:-(
pieman72

30

文字列内の単語Aに一致し、単語Bには一致しない場合。例:テキストがある場合:

1. I have a two pets - dog and a cat
2. I have a pet - dog

ペットのための犬がいて、がいないテキスト行を検索する場合は、次の正規表現を使用できます。

^(?=.*?\bdog\b)((?!cat).)*$

2行目のみが見つかります。

2. I have a pet - dog

彼は質問でそれについて言及することに失敗しましたが、OPは実際にはDOS findstrコマンドを使用しています。それはあなたが正規表現ツールで見つけることを期待する機能のごく一部のみを提供します。先読みはそれらの中にありません。(私はfindstrタグを自分で追加しました。)
アランムーア

2
ええ、はい、私は今、彼の投稿のコメントの1つで見つけました。タイトルにRegexを見ました。とにかく、私がしたように、正規表現で同じものを検索しているときに誰かがこの投稿を見つけた場合、誰かに役立つかもしれません:)コメントへの感謝
Aleks

15

パターンと照合し、ホスト言語を使用して、照合のブール結果を反転します。これにより、読みやすく、保守しやすくなります。


1
次に、(Aと〜B)の代わりに(〜AまたはB)で終わります。それは私の問題を解決しません。
2009年

1
擬似コード:文字列toTest; if(toTest.matches(A)AND!toTest.matches(B)){...}
ベンS

私はもっ​​と明確だったはずです-作品は完全に独立しているわけではありません。Aが文字列の一部と一致する場合、〜Bが残りの文字列と一致するかどうかを考慮します(ただし、必ずしも全体とは限りません)。これは、Windowsコマンドラインのfindstr関数用でした。私が見つけたのは、真の正規表現に制限されているため、重要なポイントです。
2009年

8

言及されていない簡単な解決策があったため、この古代の問題を復活させません。(正規表現バウンティクエストの調査中に質問が見つかりました。)

(Aおよび〜B)パターンに一致する必要がある状況に直面しています。

このための基本的な正規表現は、驚くほど単純です。 B|(A)

全体的な一致を無視して、Aを含むグループ1のキャプチャを調べます。

例(正規表現でのhtmlの解析に関するすべての免責事項を含む):Aは数字、Bは数字 <a tag

正規表現: <a.*?<\/a>|(\d+)

デモ(右下のペインのグループ1を見てください)

参照

状況s1、s2、s3を除いてパターンを照合する方法

次の場合を除き、パターンを照合する方法...


これは本当であるには余りにもいいですね!残念ながら、この解決策は普遍的ではなく、Emacsでは、に置き換えた後でも失敗\d[[:digit:]]ます。最初のリファレンスは、それがPerlとPHPに固有であると述べています:「PerlとPHPに固有の構文を使用して、同じことを行うバリエーションがあります。」
miguelmorin

4

通常の言語を補完するものも通常の言語ですが、それを構築するには、通常の言語用のDFAを構築し、有効な状態の変更をすべてエラーにする必要があります。例については、こちらをご覧ください。ページが言っていないことは、それがに変換さ/(ac|bd)/れたこと/(a[^c]?|b[^d]?|[^ab])/です。DFAから正規表現への変換は簡単ではありません。以前に提案したように、正規表現を変更せずに使用し、コードのセマンティクスを変更できると、より簡単です。


2
私が実際の正規表現を扱っていたら、これはすべて意味がないでしょう。正規表現は、ほとんどの言語でサポートされているパターンマッチングの曖昧なCSGっぽい(?)スペースを参照しているようです。(Aと〜B)を一致させる必要があるため、否定を削除してすべてを1つのステップで実行する方法はありません。
2009年

前述のように、findstrが真のDFA正規表現以外のことを行った場合、先読みはそれを実行します。全体的に奇妙なことに、なぜこのコマンドライン(今すぐバッチ)スタイルを実行する必要があるのか​​わかりません。それは私の手が縛られているもう一つの例です。
2009年

1
@notnot:Windowsのfindstrを使用していますか?次に、/ vが必要です。Like:findstr A inputfile | FINDSTR / VのB>最初のマッチから、OutputFile.txt A、第二マッチB.を有していないすべての行とすべての行
ジュリアーノ

ありがとう!それが実際に必要だったのです。しかし、私はそのように質問をしなかったので、より一般的な答えを得るために、ガンボに答えを出しました。
2009年

1

パターン-再

str.split(/re/g) 

パターン以外のすべてを返します。

ここでテスト


もう一度参加する必要があることをお伝えしたいと思います。
tomdemuyt

同様のアプローチがを使用している場合replace str.replace(/re/g, '')、それらを再結合する必要はありません。あなたが素敵な末尾の\ sを投げた場合も?そのようstr.replace(/\re\s?/g, '')にして、文字列の途中で何かが置き換えられた場合に発生する可能性のある重複したスペースをすべて
削除

0

ここで私の答えはあなたの問題も解決するかもしれません:

https://stackoverflow.com/a/27967674/543814

  • Replaceの代わりに、Matchを使用します。
  • グループの代わりに、グループ$1を読みます$2
  • グループ$2はそこでキャプチャされないようになりましたが、これは回避します。

例:

Regex.Match("50% of 50% is 25%", "(\d+\%)|(.+?)");

最初のキャプチャグループは、回避するパターンを指定します。最後のキャプチャグループは他のすべてをキャプチャします。単にそのグループを読んでください$2


0
(B)|(A)

次に、グループ2がキャプチャしたものを使用します...


彼はBではなくキャプチャする必要があります、彼は単にすべてのBパターンを無視することではありません。
ヘキシクル2013
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.