正規表現:AND演算子はありますか?


708

明らかに、|(パイプ?)を使用してを表すことができますが、同様ORに表す方法はありANDますか?

具体的には、特定のフレーズのすべてを含むが、特定の順序ではないテキストの段落を照合します。


1
テキスト内のフレーズを検索したいということですか?そのようなフレーズはそれぞれ、特定のフレーズ内の単語の有効な順列です。
Nietzche-jou、

2
3〜4つの答えは無視するので、これをここに置きます。$で終わっていない限り、先読みは各句の同じ長さに一致しません。1つの先読みは4文字に一致し、別の6は一致する可能性があります。たとえば、(?= a *)(?= aab)はaabaaaabaに一致します
Zachary Vance

2
「AND」演算子には「スペース」文字のみを使用してみてください。

1 I'd like to match paragraphs of text。2. 順不同のテキスト含まれています。1番は解釈の自由があります。2番はいくつかの方法で行うことができます。方法1 (?:(?:(?(1)(?!))\b(phrase1)\b.*?|(?(2)(?!))\b(phrase2)\b.*?)){2}:、方法2:(?=.*\bphrase1\b)(?=.*\bphrase2\b)ここで、この場合の段落のマッチングは、段落の定義が正式化されるまで未定義です。

回答:


385

消費しない正規表現を使用します。

典型的な(つまり、Perl / Java)表記は次のとおりです。

(?=expr)

これは、「exprに一致するが、その後、元の一致ポイントで一致を続ける」ことを意味します。

これらは好きなだけ行うことができ、これが「and」になります。例:

(?=match this expression)(?=match this too)(?=oh, and this)

データの一部を保存する必要がある場合は、非消費式の中にキャプチャグループを追加することもできます。


3
perl -e "q {some stuff and things} =〜/(?= some)(?= stuff)(?= things)/?print 'yes':print 'no'"は 'no'を出力します。
ロバートP

27
この特定の例は、ポジティブルックアヘッドアサーションと呼ばれていることに注意してください。「and」以外にも用途があります。テキストは消費されないことに注意してください。
ストレージャー、2009年

7
このように(?=)を使用すると、正常に実行できない正規表現になります。しかし、これ |との結合アナログです。OPは、彼が問題を解決するだろうと彼が考えていることにおいて、ただ間違っています。
Nietzche-jou

10
perl -e "q {some stuff and things} =〜/(?=.*some)(?=.*stuff)(?=.*things)/?print 'yes':print 'no'"
クリス

3
あなたの答えにperlコードの簡単な例を追加していただけますか?
Pithikos

343

他のレスポンダーの一部が言ったように、先読みを使用する必要がありますが、先読みは、ターゲット単語と現在の一致位置の間の他の文字を考慮する必要があります。例えば:

(?=.*word1)(?=.*word2)(?=.*word3)

.*最初の先読みでは、それはそれは「単語1」になる前に必要しかし多くの文字を一致させることができます。次に、一致位置がリセットされ、2番目の先読みで「word2」が検索されます。もう一度リセットすると、最後の部分は「word3」に一致します。チェックしている最後の単語なので、先読みである必要はありませんが、害はありません。

段落全体を一致させるには、両端に正規表現をアンカーし、最後.*に追加して残りの文字を消費する必要があります。Perlスタイルの表記を使用すると、次のようになります。

/^(?=.*word1)(?=.*word2)(?=.*word3).*$/m

'm'修飾子はマルチラインモード用です。段落の境界(正規表現では「行の境界」)でと^$一致させます。この場合、「s」修飾子を使用しないことが重要です。これにより、ドットのメタ文字が改行や他のすべての文字と一致します。

最後に、長い単語の断片だけでなく、単語全体を照合する必要があるため、単語の境界を追加する必要があります。

/^(?=.*\bword1\b)(?=.*\bword2\b)(?=.*\bword3\b).*$/m

8
まさにその通りです-これについてのチュートリアルもあります!ocpsoft.org/tutorials/regular-expressions/and-in-regex
リンカーン

9
どうも

1
先読みの最良の用途の1つを示す明確で簡潔な回答の+1(パスワードの一致率をカウントするハックなどの用途とは異なります)。:)
zx81 2014年

1
@リアム:。MySQLはPOSIX EREフレーバーを使用するため、使用しません。それはパフォーマンスを優先して機能を効果的に犠牲にします。詳細については、こちらをご覧ください
アランムーア

3
交換する.*[\s\S]*あなたは、新しい行を持っている場合はJavaScriptで.新しい行を一致していませんジャバスクリプトの正規表現エンジン内および修飾子とに行うことができない
ウェズリー・スミス

41

この例を見てください:

2つの正規表現AとBがあり、両方に一致させたいので、疑似コードでは次のようになります。

pattern = "/A AND B/"

次のようにAND演算子を使用せずに記述できます。

pattern = "/NOT (NOT A OR NOT B)/"

PCRE:

"/(^(^A|^B))/"

regexp_match(pattern,data)

24
これは正式な論理に関しては真実ですが、ここではまったく役に立ちません。正規表現では、NOTはANDよりも表現が難しい場合があります。
アランムーア

@marvin_dpr他の提案で(?=expr)は機能しませんでしたが、CMakeでは私にとっては機能しました。実装に依存しているようです。
Melebius 2013年

38
^正規表現構文で「文字列の先頭」を意味するのではないですか?
Lambda Fairy

3
一般的な正規表現で^は、文字クラスの先頭でのみ否定です。CMakeが本当にファンキーなことをしていない限り(パターンマッチング言語の "regex"の呼び出しが誤解を招く、または正しくないと見なされるまで)、私はそれがあなたのために機能したのは孤立した事故だったと思います。
Tripleee、2015

29

正規表現を使用してそれを行うことができますが、おそらく他のことをしたいと思うでしょう。たとえば、複数の正規表現を使用し、それらをif句で組み合わせます。

次のように、標準の正規表現を使用してすべての可能な順列を列挙できます(任意の順序でa、b、cに一致します)。

(abc)|(bca)|(acb)|(bac)|(cab)|(cba)

ただし、2つ以上の項がある場合、これは非常に長く、おそらく非効率的な正規表現になります。

PerlやJavaなどの拡張正規表現バージョンを使用している場合は、これを行うための優れた方法があります。他の回答は、肯定的な先読み操作の使用を提案しています。


10
あなたのアプローチは、破滅的なバックトラックを伴う3つの先読みよりも非効率だとは思いません。もちろん、書く方が長くなりますが、パターンを自動的に簡単に生成できることに注意してください。を使用すると、より速く失敗するように改善できることに注意してくださいa(bc|cb)|b(ac|ca)|c(ab|ba)。そして最も重要なのは、すべての正規表現のフレーバーで使用できることです。
Casimir et Hippolyte 2013年

27

AND演算子は、RegExp構文では暗黙的です。
代わりにOR演算子をパイプで指定する必要があります。
次のRegExp:

var re = /ab/;

文字意味a 手紙をb
グループでも機能します:

var re = /(co)(de)/;

それはグループ意味co グループをde
(暗黙の)ANDをORで置き換えるには、次の行が必要です。

var re = /a|b/;
var re = /(co)|(de)/;

29
残念ながら、これはOPが要求したものではありません。これはその順序で何かを見つけますが、彼らはそれらを任意の順序で望んでいました。正しい答えは以下のstackoverflow.com/users/20938/alan-mooreで答えを確認してください。
JESii 2014

1
@JESiiご指摘ありがとうございます。正解です。Hugowareからの質問を誤解しています。特に彼の最初の文に焦点を当てました。AlanMooreが書いたように、正しい答えは先読み演算子の適切な使用です。とにかく、私の賛成意見はすでに賛成されているので、誰かが私の説明が役立つと思うかもしれないので、すべてを捨てるつもりはありません。よろしく。
エマヌエーレデルグランデ

13

あなたの場合、いくつかの一致する結果に対してANDを実行することはできませんか?擬似コードで

regexp_match(pattern1, data) && regexp_match(pattern2, data) && ...

3
ルールのデータテーブルであるコードがあり、ルールの有効性をテストするための単一の正規表現パターン一致文字列がある状況にあります。複数のテストに移行することは、私の場合、そして一般的に他の人々の場合も同様にできることではありません!
アランウルフ2015

11

なぜawkを使わないのですか?
awk正規表現ANDを使用すると、ORの問題は非常に簡単になります

awk '/WORD1/ && /WORD2/ && /WORD3/' myfile

9

Perl正規表現を使用する場合は、正の先読みを使用できます。

例えば

(?=[1-9][0-9]{2})[0-9]*[05]\b

100より大きい数値で、5で割り切れる


8

出力を別の正規表現にパイプすることができます。grepを使用すると、これを行うことができます。

grep A | grep B


8

受け入れられた答えに加えて

私はあなた方の何人かに物事をより明確にするいくつかの実用的な例を提供します。たとえば、次の3行のテキストがあるとします。

[12/Oct/2015:00:37:29 +0200] // only this + will get selected
[12/Oct/2015:00:37:x9 +0200]
[12/Oct/2015:00:37:29 +020x]

ここでのデモを参照してください DEMO

ここで行うのは、+記号を選択することですが、2つの数値の後にスペースがあり、4つの数値の前にある場合のみです。これらが唯一の制約です。この正規表現を使用してそれを実現します。

'~(?<=\d{2} )\+(?=\d{4})~g'

式を分離すると、異なる結果が得られることに注意してください。

または、タグの間にあるテキストを選択したいかもしれません...しかしタグではありません!それからあなたは使うことができます:

'~(?<=<p>).*?(?=<\/p>)~g'

このテキストの場合:

<p>Hello !</p> <p>I wont select tags! Only text with in</p> 

ここでのデモを参照してください DEMO


受け入れられた回答はどれですか。将来の私のためにそれにリンクを追加してください。
James Brown、

6

順序は常に正規表現の構造に含まれています。希望どおりの結果を得るには、入力文字列をさまざまな表現に対して複数回照合する必要があります。

あなたがしたいことは単一の正規表現では不可能です。


技術的に不可能ではありませんが、実装する価値はありません。なぜ誰かが反対票を投じたのか分からない...
ロバートP

13
おそらくそれが可能であるだけでなく、正規表現のフレーバーが先読みをサポートしていることを前提として、それは単純です。そしてそれは良い賭けです。今日の主要なプログラミング言語のほとんどはそれらをサポートしています。
アランムーア

3

正規表現の外でANDを使用します。PHPの先読み演算子は私には機能しないようでしたが、代わりにこれを使用しました

if( preg_match("/^.{3,}$/",$pass1) && !preg_match("/\s{1}/",$pass1))
    return true;
else
    return false;

上記の正規表現は、パスワードの長さが3文字以上で、パスワードにスペースが含まれていない場合に一致します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.