正则表达式:是否有AND运算符?


706

显然,您可以使用|(pipe?)表示OR,但是也有一种表示AND方法吗?

具体来说,我想匹配包含某个短语的全部但没有特定顺序的文本段落。


1
您是否要在文本中查找短语,其中每个这样的短语都是给定短语中单词的有效排列?
尼采茹2009年

2
我将其放在这里是因为三个或四个答案忽略了它。除非每个子句以$结尾,否则Lookahead的每个子句的长度都不相同。一个前瞻可以匹配四个字符,另一个可以匹配六个字符。例如,(?= a *)(?= aab)可以匹配aabaaaaba
Zachary Vance 2010年

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)在这种情况下,在这种情况下,在定义段落的形式化之前,该段落的匹配是不确定的。

Answers:


385

使用非消耗性的正则表达式。

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

(?=expr)

这表示“ match expr,但此后继续在原始匹配点进行匹配”。

您可以根据需要执行任意多个操作,这将是一个“与”。例:

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

如果需要在其中使用一些数据,甚至可以在非使用表达式中添加捕获组。


3
perl -e“ q {一些东西} =〜/(?= some)(?= stuff)(?= things)/?print'yes':print'no'”打印'no'。
罗伯特·P

27
应该提到的是,这个特定的例子称为正向超前断言。它具有“和”以外的其他用途。请注意,该文本不会被使用。
斯特拉格

7
像这样使用(?=)会导致正则表达式永远无法成功。但这 |的合取模。OP认为他能解决他的问题只是错误的。
尼采茹09年

10
perl -e“ q {一些东西} =〜/(?=.*some)(?=.*stuff)(?=.*things)/?print'yes':print'no'”
kriss

3
您能否在答案中的perl代码中添加一些简单的示例?
2011年

343

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

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

.*第一先行让它符合它需要它得到“字词1”之前,无论多少个字符。然后重设比赛位置,第二个超前查找“ 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
非常感谢。*这有所作为
Gennadiy Ryabkin

1
+1表示简洁明了的答案,显示了先行的最佳用法(与黑客等用于计算密码匹配百分比的用法不同)。:)
zx81 2014年

1
@利亚姆:。MySQL使用POSIX ERE风格,所以没有。在我看来,它实际上是为了牺牲性能而牺牲了功能。还有更多的信息在这里
艾伦·摩尔

3
更换.*[\s\S]*在JavaScript,如果你有新的线路为.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在CMake中对我有用,而其他建议则(?=expr)不行。它似乎取决于实现。
Melebius

38
^regex语法中的意思不是“字符串开头”吗?
Lambda Fairy

3
通常,在正则表达式中,^否定仅在字符类的开头。除非CMake所做的事情确实很时髦(以至于将其模式匹配语言称为“ regex”可能被误导或认为是错误的),否则我猜想它对您有用是一个孤立的事故。
2015年

29

您可以使用正则表达式执行此操作,但可能还会需要其他一些功能。例如,使用多个regexp并将它们组合在if子句中。

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

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

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

如果您使用的是扩展的正则表达式版本,例如Perl或Java,则它们有更好的方法来执行此操作。其他答案建议使用正向超前操作。


10
我认为您的方法在灾难性的回溯方面不会比3个先行方法低效。确保更长的时间来写,但是请注意,您可以轻松地自动生成模式。请注意,您可以使用改进它使其更快地失败a(bc|cb)|b(ac|ca)|c(ab|ba)。最重要的是,您可以在所有正则表达式中使用它。
Casimir et Hippolyte

26

AND运算符在RegExp语法中是隐式的。
必须使用管道指定OR运算符。
以下RegExp:

var re = /ab/;

指字母a 字母b
它也适用于组:

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

它表示小组co 小组de
用OR替换(隐式)AND将需要以下几行:

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

29
不幸的是,这不是OP所要求的。这将按该顺序查找任何内容,而他们希望以任何顺序查找它们。通过stackoverflow.com/users/20938/alan-moore找出答案,以下是正确的答案。
JESii 2014年

1
@JESii感谢您的观点,您说得对,我误解了Hugoware提出的问题,我特别关注他的第一句话。正确的答案是正确地使用前瞻运算符,如AlanMoore所写。无论如何,我认为有人可能会认为我的澄清很有用,因为已经被赞成,所以我不会丢掉所有东西。问候。
Emanuele Del Grande '18

13

在您的情况下,是否可以对多个匹配结果进行“与”运算?用伪代码

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

3
我遇到的情况是,我有一些代码是规则的数据表,并且带有一个正则表达式模式匹配字符串来测试规则的有效性。在我的情况下,我无法进行多项测试,在其他人的情况下,也是如此!
艾伦·沃尔夫

11

为什么不使用awk?
使用awk regex AND,或很简单

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

除了接受的答案

我将为您提供一些实际示例,以使您中的一些人更加清楚。例如,假设我们有这三行文字:

[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


接受的答案是哪个?请为将来添加链接。
詹姆斯·布朗

6

该顺序始终隐含在正则表达式的结构中。为了完成所需的操作,您必须针对不同的表达式多次匹配输入字符串。

单个正则表达式是不可能做到的。


从技术上讲这不是不可能的,但也不值得实施。我不知道为什么有人不赞成……
罗伯特·P

13
可能是因为这不仅可能,而且很简单,假设您的regex风格支持先行。那是一个很好的选择;当今大多数主要的编程语言都支持它们。
艾伦·摩尔

3

在正则表达式外使用AND。在PHP中,先行运算符似乎并不适合我,而是我使用了它

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

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.