866

Obviously, you can use the | (pipe?) to represent OR, but is there a way to represent AND as well?

Specifically, I'd like to match paragraphs of text that contain ALL of a certain phrase, but in no particular order.

4

14 回答 14

451

使用非消耗正则表达式。

典型的(即 Perl/Java)表示法是:

(?=表达式)

这意味着“匹配expr,但之后在原始匹配点继续匹配”。

您可以随心所欲地执行这些操作,这将是一个“和”。例子:

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

如果您需要在其中保存一些数据,您甚至可以在非消费表达式中添加捕获组。

于 2009-01-22T16:58:53.587 回答
411

您需要像其他一些响应者所说的那样使用前瞻,但前瞻必须考虑其目标词和当前匹配位置之间的其他字符。例如:

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

.*第一个前瞻中,它可以匹配在到达“word1”之前需要的任意多个字符。然后匹配位置被重置,第二个前瞻寻找“word2”。再次重置,最后部分匹配“word3”;因为它是您要检查的最后一个单词,所以没有必要将它放在前瞻中,但这并没有什么坏处。

为了匹配整个段落,您需要在两端锚定正则表达式并添加一个final.*来消耗剩余的字符。使用 Perl 风格的表示法,这将是:

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

'm' 修饰符用于多线模式;它让^and$匹配段落边界(正则表达式中的“行边界”)。在这种情况下,您必须不要使用 's' 修饰符,它可以让点元字符匹配换行符以及所有其他字符。

最后,您要确保匹配整个单词,而不仅仅是较长单词的片段,因此您需要添加单词边界:

/^(?=.*\bword1\b)(?=.*\bword2\b)(?=.*\bword3\b).*$/m
于 2009-01-22T20:04:11.200 回答
51

看这个例子:

我们有 2 个正则表达式 A 和 B,我们想匹配它们,所以在伪代码中它看起来像这样:

pattern = "/A AND B/"

它可以不使用 AND 运算符来编写,如下所示:

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

在 PCRE 中:

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

regexp_match(pattern,data)
于 2011-04-20T12:11:40.323 回答
37

AND 运算符隐含在 RegExp 语法中。
OR 运算符必须用管道指定。
以下正则表达式:

var re = /ab/;

表示字母a 字母b
它也适用于组:

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

这意味着组co de
用 OR 替换(隐式)AND 需要以下几行:

var re = /a|b/;
var re = /(co)|(de)/;
于 2014-06-30T11:25:56.810 回答
30

你可以用一个正则表达式来做到这一点,但可能你会想要其他的。例如,使用几个正则表达式并将它们组合在一个 if 子句中。

您可以使用标准正则表达式枚举所有可能的排列,如下所示(以任意顺序匹配 a、b 和 c):

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

但是,如果您有多个术语,这会导致非常长且可能效率低下的正则表达式。

如果您使用一些扩展的正则表达式版本,例如 Perl 或 Java,他们有更好的方法来做到这一点。其他答案建议使用积极的前瞻操作。

于 2009-01-22T18:07:04.837 回答
13

Is it not possible in your case to do the AND on several matching results? in pseudocode

regexp_match(pattern1, data) && regexp_match(pattern2, data) && ...
于 2009-01-22T16:57:52.760 回答
12

为什么不使用awk?
使用 awk 正则表达式 AND,OR 很简单

awk '/WORD1/ && /WORD2/ && /WORD3/' myfile
于 2013-12-27T13:49:46.337 回答
10

如果你使用 Perl 正则表达式,你可以使用积极的前瞻:

例如

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

将是大于 100 且可被 5 整除的数字

于 2009-01-22T16:59:30.543 回答
9

除了接受的答案

我将为你们提供一些实际的例子,让你们中的一些人更清楚。例如,假设我们有这三行文本:

[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

我们在这里要做的是选择 + 号,但前提是它在两个带空格的数字之后并且在四个数字之前。这些是唯一的限制。我们将使用这个正则表达式来实现它:

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

请注意,如果您将表达式分开,它将给您不同的结果。

或者也许您想在标签之间选择一些文本......但不是标签!然后你可以使用:

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

对于这个文本:

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

在此处查看演示 DEMO

于 2015-11-13T11:30:56.370 回答
8

The order is always implied in the structure of the regular expression. To accomplish what you want, you'll have to match the input string multiple times against different expressions.

What you want to do is not possible with a single regexp.

于 2009-01-22T16:56:05.853 回答
8

您可以将输出通过管道传输到另一个正则表达式。使用 grep,您可以这样做:

grep A | grep B

于 2014-11-20T21:36:21.873 回答
5

在正则表达式之外使用 AND。在 PHP 中,前瞻运算符似乎对我不起作用,而是我使用了这个

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

如果密码长度为 3 个或更多字符并且密码中没有空格,则上述正则表达式将匹配。

于 2011-09-09T18:13:04.763 回答
2

((yes).*(no))|((no).*(yes))

yes将匹配同时具有这两者的句子no,而不管它们出现的顺序:

Do i like cookies? **Yes**, i do. But milk - **no**, definitely no.

**No**, you may not have my phone. **Yes**, you may go f yourself.

两者都匹配,忽略大小写。

于 2020-11-25T10:16:08.287 回答
2

这是“and”运算符的一种可能的“形式”:

以下面的正则表达式为例:

如果我们想匹配没有“e”字符的单词,我们可以这样做:

/\b[^\We]+\b/g
  • \W表示不是“单词”字符。
  • ^\W表示“单词”字符。
  • [^\We]表示“word”字符,但不是“e”。

实际操作:没有 e 的单词

正则表达式的“and”运算符

我认为这种模式可以用作正则表达式的“和”运算符。

一般来说,如果:

  • A = not a
  • B = not b

然后:

[^AB] = not(A or B) 
      = not(A) and not(B) 
      = a and b

差异集

所以,如果我们想在正则表达式中实现差异集的概念,我们可以这样做:

a - b = a and not(b)
      = a and B
      = [^Ab]
于 2021-05-06T09:22:28.423 回答