web-dev-qa-db-ja.com

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

明らかに、ORを表すために|(pipe?)を使うことができますが、ANDを表す方法もありますか?

具体的には、特定のフレーズのALLを含むテキストの段落を、特定の順序で一致させたいのです。

603
Hugoware

消費しない正規表現を使用してください。

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

(?= expr )

これは、 "match expr が、その後も元のマッチポイントでマッチングを続ける"という意味です。

あなたはあなたが望むようにこれらの多くをすることができます、そしてこれは "と"になります。例:

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

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

340
Jason Cohen

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

(?=.*Word1)(?=.*Word2)(?=.*Word3)

最初の先読みの.*は、それが "Word1"に到達する前に必要な多くの文字と一致させます。その後、一致位置がリセットされ、2番目の先読みが "Word2"を探し出します。もう一度リセットすると、最後の部分は「Word3」と一致します。これはあなたがチェックしている最後のWordなので、先読みする必要はありませんが、問題ありません。

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

/^(?=.*Word1)(?=.*Word2)(?=.*Word3).*$/m

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

最後に、長い単語の断片だけでなく単語全体を一致させるようにしたいので、Wordの境界を追加する必要があります。

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

この例を見てください。

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

pattern = "/A AND B/"

このようにAND演算子を使わずに書くことができます。

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

pCREでは:

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

regexp_match(pattern,data)
29
fanjabi

あなたは正規表現でそれをすることができますが、おそらくあなたは他のものに望むでしょう。たとえば、いくつかの正規表現を使用してそれらをif節で結合します。

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

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

しかし、もしあなたが2つ以上の用語を持っているなら、これは非常に長くそしておそらく非効率的な正規表現を作ります。

PerlやJavaのような、拡張された正規表現バージョンを使っているのであれば、もっと良い方法があります。他の回答では、積極的な先読み操作を使用することを提案しています。

27
Juha Syrjälä

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

var re = /ab/;

文字a _および_ は文字bを意味します。
これはグループでも動作します。

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

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

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

あなたのケースでは、いくつかのマッチング結果に対してANDをとることは不可能ですか?擬似コードで

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

どうしてawkを使わないの?
awk regex ANDでは、OR重要なことはとても簡単です

awk '/Word1/ && /Word2/ && /Word3/' myfile
9
mug896

Perlの正規表現を使っているなら、前向きな先読みを使うことができます。

例えば

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

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

8
jpalecek

あなたの出力を別の正規表現に渡すことができます。 grepを使うと、これができます。

grep A | grep B

6

一般的な回答に加えて

私は、あなたに物事をより明確にするいくつかの実用的な例をあなたに提供します。たとえば、次の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 _

5
DevWL

順序は常に正規表現の構造に含まれています。あなたが望むものを達成するために、あなたは異なる表現に対して入力文字列を複数回マッチさせる必要があるでしょう。

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

2
pilif

正規表現の外側でANDを使用してください。 PHP先読み演算子ではうまく動作しないようでしたが、代わりにこれを使用しました

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

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

0
Hammad Khan