正则表达式可以匹配两个正则表达式之间的交集?

时间:2014-06-08 02:29:21

标签: regex

给定几个正则表达式,我们可以编写一个等于它们交集的正则表达式吗?

例如,给定两个正则表达式c[a-z][a-z][a-z][aeiou]t,它们的交集包含catcut,可能还有更多。我们如何为它们的交集编写正则表达式?

感谢。

5 个答案:

答案 0 :(得分:7)

前瞻示例易于使用,但从技术上讲不再是常规语言。但是,可以采用两种常规语言的交集,并且这种补语是有规律的。

首先请注意,正则表达式可以转换为NFA;它们都是表达常规语言的方式。

其次,根据德莫根定律,

De Morgan's Law as used in the intersection of two regular languages

因此,这些是计算两个RegEx交集的步骤:

  • 将两个RegEx转换为NFA。
  • 计算两个NFA的补充。
  • 计算两个补语的并集。
  • 计算该联盟的补充。
  • 将生成的NFA转换为RegEx。

一些消息来源:

答案 1 :(得分:6)

正则表达式中的逻辑AND由

表示
(?=...)(?=...)

所以,

(?=[a-z][aeiou]t)(?=c[a-z][a-z])

Regular expression visualization

答案 2 :(得分:5)

从数学角度讲,两种常规语言的交集是常规的,因此必须有一个接受它的正则表达式。

通过相应的NFA构建它可能是最简单的。考虑与两个正则表达式相对应的两个NFA。新状态Q是来自两个NFA的对(Q1,Q2)。如果第一个NFA中存在转换(P1,x,Q1),第二个NFA中存在(P2,x,Q2),那么只有转换((P1,P2),x,(Q1,Q2) ))在新的NFA中。如果Q1和Q2都是初始/最终,则新状态(Q1,Q2)为初始/最终。

如果你使用具有ε-移动的NFA,那么对于每个转变(P1,ε,Q1),对于所有状态P2将存在转变((P1,P2),ε,(Q1,P2))。同样地,对于第二个NFA中的ε-移动。

现在使用任何已知算法将新NFA转换为正则表达式,就是这样。

至于PCRE,严格来说,它们不是正则表达式。在一般情况下无法做到这一点。有时您可以使用前瞻,例如^(?=regex1$)(?=regex2$),但这只适用于匹配整个字符串,对于搜索或嵌入其他regexp无益。没有锚定,两个前瞻可能最终匹配不同长度的字符串。这不是交集。

答案 3 :(得分:4)

首先,让我们就条款达成一致。我的语法假设是

  

几个正则表达式的交集是一个匹配字符串的正则表达式   每个组件正则表达式也匹配。

常规选项

要检查两种模式的交集,通用方法是(伪代码):

if match(regex1) && match(regex2) { champagne for everyone! }

正则表达式选项

在某些情况下,你可以对前瞻做同样的事情,但是对于一个复杂的正则表达式来说,这样做除了使你的正则表达式对你的敌人更加模糊之外没什么好处。为什么收益不大?因为引擎必须多次解析整个字符串。

布尔AND

AND检查字符串是否完全符合regex1和regex2的一般模式是:

^(?=regex1$)(?=regex2$)

每个前瞻中的$确保每个字符串与模式匹配,仅此而已。

与AND

匹配

当然,如果您不想只检查AND的布尔值但也要进行一些实际匹配,那么在前瞻之后,您可以添加一个点星来使用该字符串:

^(?=regex1$)(?=regex2$).*

或者......在检查完第一个条件后,只需匹配第二个条件:

^(?=regex1$)regex2$

这是一种用于密码验证的技术。有关详细信息,请参阅Mastering Lookahead and Lookbehind

红利部分:Regexes联盟

不要在交叉点上工作,而是假设您对以下正则表达式的并集感兴趣,即与这些正则表达式匹配的正则表达式:

  1. 捕获
  2. CAT1
  3. CAT2
  4. CAT3
  5. CAT5
  6. 这是通过交替|运算符完成的:

    catch|cat1|cat2|cat3|cat5
    

    此外,这种正则表达式通常可以被压缩,如:

    cat(?:ch|[1-35]) 
    

答案 4 :(得分:0)

对于And操作,我们在RegEx中有这样的东西

(REGEX)(正则表达式)

举个例子

'Cat'.match(/^([A-Za-z]+)([aeiouAEIOU]+)([A-Za-z]+)$/)
["Cat", "C", "a", "t"]
'Ca'.match(/^([A-Za-z]+)([aeiouAEIOU]+)([A-Za-z]+)$/)
//null
'Cat123'.match(/^([A-Za-z]+)([aeiouAEIOU]+)([A-Za-z]+)$/)
//null

<强>,其中

([A-Za-z]+)  //Match All characters

([aeiouAEIOU]+) //Match all vowels

将两者合并将匹配

    ([A-ZA-Z] +)([aeiouAEIOU] +)([A-ZA-Z] +)

<强>例如

'Hmmmmmm'.match(/^([A-Za-z]+)([aeiouAEIOU]+)([A-Za-z]+)$/)
//null
'Stckvrflw'.match(/^([A-Za-z]+)([aeiouAEIOU]+)([A-Za-z]+)$/)
null
'StackOverflow'.match(/^([A-Za-z]+)([aeiouAEIOU]+)([A-Za-z]+)$/)
["StackOverflow", "StackOverfl", "o", "w"]