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

Regular Expressions: Is there an AND operator?

显然,您可以使用EDOCX1(管道?)代表OR,但有没有办法代表AND

具体地说,我想匹配包含所有特定短语但没有特定顺序的文本段落。


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

典型的(即Perl/Java)符号是:

(?=expr)

这意味着"match expr",但之后继续在原始匹配点进行匹配。

您可以随心所欲地执行这些操作,这将是一个"and."示例:

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

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


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

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

第一个lookahead中的.*允许它匹配在到达"word1"之前所需的许多字符。然后重置匹配位置,第二个先行查找查找"word2"。重新设置,最后一部分与"word3"匹配;因为这是您要检查的最后一个单词,所以不必预先查看,但不会造成伤害。

为了匹配整个段落,需要在两端锚定regex,并添加一个最后的.*来使用剩余的字符。使用Perl样式的表示法,可以是:

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

"m"修饰符用于多行模式;它允许^$在段落边界处匹配(regex中的"行边界")。在这种情况下,必须不要使用"s"修饰符,它允许点元字符与换行符以及所有其他字符匹配。

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

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


看看这个例子:

我们有两个regexps a和b,我们希望两者都匹配,所以在伪代码中,它看起来如下:

1
pattern ="/A AND B/"

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

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

在PCRE:

1
2
3
"/^(^A|^B)/"

regexp_match(pattern,data)


你可以用正则表达式来实现这一点,但可能你还需要一些其他的。例如,使用几个regexp并在if子句中组合它们。

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

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

但是,如果您有多个条件,这将导致非常长的、可能效率很低的regexp。

如果您使用的是一些扩展版本,如Perl或Java,它们有更好的方法来实现这一点。其他的答案也建议使用积极的前瞻性操作。


and运算符在regexp语法中是隐式的。
或运算符必须用管道指定。
以下regexp:

1
var re = /ab/;

表示字母a和字母b
它还与以下组一起工作:

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

指EDOCX1组〔9〕和EDOCX1组〔10〕。
将(隐式)和替换为或需要以下行:

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


在您的情况下,是否不可能对几个匹配结果执行和操作?伪码

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


为什么不用锥子?有了awk regex和,或者说很简单

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

如果使用Perl正则表达式,则可以使用正的lookahead:

例如

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

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


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

grep A | grep B


除了接受的答案

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

1
2
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]

在这里看到演示演示

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

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

注意,如果分离表达式,它将给出不同的结果。

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

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

对于本文:

1
2
3
4
5
<p>
Hello !
</p> <p>
I wont select tags! Only text with in
</p>

在这里看到演示演示


在正则表达式的结构中,顺序总是隐含的。要实现您想要的,您必须针对不同的表达式多次匹配输入字符串。

对于单个regexp,您想要做的是不可能的。


在正则表达式之外使用。在PHP中,lookahead操作符似乎不适合我,而是使用了这个

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

如果密码长度大于或等于3个字符,并且密码中没有空格,则上述regex将匹配。