ChatGPT解决这个技术问题 Extra ChatGPT

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

显然,您可以使用 |(管道?)来表示 OR,但有没有办法也表示 AND

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

您的意思是要在文本中查找短语,其中每个这样的短语都是给定短语中单词的有效排列?
我把它放在这里是因为三四个答案忽略它。 Lookahead 不匹配每个子句的相同长度,除非它们以 $ 结尾。一个前瞻可以匹配四个字符,另一个可以匹配 6 个字符。例如,(?=a*)(?=aab) 将匹配 aabaaaaba
尝试仅对“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) 其中,这种情况下的段落匹配是不确定的,直到段落的定义被形式化。

J
Jason Cohen

使用非消耗正则表达式。

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

(?=表达式)

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

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

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

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


perl -e "q{some stuff and things} =~ /(?=some)(?=stuff)(?=things)/ ? print 'yes' : print 'no'" 打印出'no'。
应该提到的是,这个特定的例子被称为肯定的前瞻断言。除了“和”之外,它还有其他用途。请注意,文本不会被消耗。
像这样使用 (?=) 会导致正则表达式永远不会成功。但它是 | 的连词类比。 OP在他认为可以解决他的问题方面是错误的。
perl -e "q{some stuff and things} =~ /(?=.*some)(?=.*stuff)(?=.*things)/ ? print 'yes' : print 'no'"
您能否在答案中添加一些 perl 代码中的简单示例?
A
Alan Moore

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

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

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

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

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

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

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

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

完全正确 - 还有一个关于这个的教程! ocpsoft.org/tutorials/regular-expressions/and-in-regex
非常感谢。*这会有所作为
+1 以获得清晰简洁的答案,展示了前瞻的最佳用途之一(与黑客计算密码匹配百分比的用途不同)。 :)
@利亚姆:。 MySQL 使用 POSIX ERE 风格,所以没有。它有效地牺牲了有利于性能的功能,这在我看来是合理的。还有更多信息here
如果您有新行,请在 javascript 中将 .* 替换为 [\s\S]*,因为 javascript 的正则表达式引擎中的 . 不匹配新行并且不能使用修饰符
f
fanjabi

看这个例子:

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

pattern = "/A AND B/"

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

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

在 PCRE 中:

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

regexp_match(pattern,data)

就形式逻辑而言,这是正确的,但在这里绝对没有帮助。在正则表达式中,NOT 比 AND 更难表达。
@marvin_dpr 它在 CMake 中对我有用,而另一个建议 (?=expr) 没有。它似乎依赖于实现。
^ 不是正则表达式语法中的“字符串开头”吗?
在一般的正则表达式中,^ 仅在字符类的开头是否定的。除非 CMake 正在做一些非常时髦的事情(以至于称他们的模式匹配语言“正则表达式”可能会被视为误导或不正确),否则我猜它对你有用的事实是一个孤立的事故。
这个绝对错误的答案怎么会得到如此多的支持?!在 /(^(^A|^B))/ PCRE 中,^ 表示“行首”而不是否定。也许使用 negative lookahead(?!…),例如 (?!(?!A)|(?!B)))可以获得一些运气,但使用 ^ 肯定不行。
J
Jair López

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

var re = /ab/;

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

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

它表示组 co ANDde
将(隐式)AND 替换为 OR 需要以下行:

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

不幸的是,这不是 OP 所要求的。这会按该顺序找到任何东西,而他们希望它们按任何顺序排列。查看下面stackoverflow.com/users/20938/alan-moore的答案,哪个是正确的。
@JESii 谢谢你的观点,你是对的,我误解了 Hugoware 的问题,我特别关注他的第一句话。正如 AlanMoore 所写,正确的答案是正确使用前瞻运算符。无论如何,我认为有人可能会发现我的澄清很有用,因为已经被赞成,所以我不会把所有东西都扔掉。问候。
J
Juha Syrjälä

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

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

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

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

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


我认为您的方法不会比 3 次前瞻以及灾难性的回溯效率低下。当然写起来会更长,但请注意,您可以轻松地自动生成模式。请注意,您可以使用 a(bc|cb)|b(ac|ca)|c(ab|ba) 改进它以更快地失败。最重要的是,您可以将它与所有正则表达式一起使用。
u
user54579

在您的情况下,是否不可能对多个匹配结果进行 AND 操作?在伪代码中

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

我的情况是,我有一些代码是规则的数据表,使用单个正则表达式模式匹配字符串来测试规则的有效性。在我的情况下,我无法进行多个测试,在其他人的情况下也是如此!
@AlanWolfe我现在正在处理完全相同的情况......所以你找到处理逻辑AND的正确方法了吗?
m
mug896

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

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

p
pilif

顺序总是隐含在正则表达式的结构中。要完成您想要的,您必须多次将输入字符串与不同的表达式进行匹配。

使用单个正则表达式无法实现您想要做的事情。


这在技术上并非不可能,但不值得实施。我不知道为什么有人拒绝投票...
可能是因为它不仅可能,而且很简单,假设您的正则表达式支持前瞻。这是一个不错的选择;今天的大多数主要编程语言都支持它们。
j
jpalecek

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

例如

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

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


A
Antoine

除了接受的答案

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

[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


哪个答案是公认的答案?请为未来的我添加一个链接。
g
garbagecollector

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

grep A | grep B


H
Hammad Khan

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

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

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


h
hrs

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

将匹配同时具有 yesno 的句子,而不管它们出现的顺序:

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.

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


非常有效率。
l
lochiwei

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

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

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

/\b[^\We]+\b/g

\W 表示不是“单词”字符。

^\W 表示“单词”字符。

[^\We] 表示“单词”字符,而不是“e”。

看看它的实际效果:word without e

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

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

一般来说,如果:

A = 不是

= 不是 b

然后:

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

差异集

因此,如果我们想在正则表达式中实现 difference set 的概念,我们可以这样做:

a - b = a and not(b)
      = a and B
      = [^Ab]