给定几个正则表达式,我们可以编写一个等于它们交集的正则表达式吗?
例如,给定两个正则表达式c[a-z][a-z]
和[a-z][aeiou]t
,它们的交集包含cat
和cut
,可能还有更多。我们如何为它们的交集编写正则表达式?
感谢。
答案 0 :(得分:7)
前瞻示例易于使用,但从技术上讲不再是常规语言。但是,可以采用两种常规语言的交集,并且这种补语是有规律的。
首先请注意,正则表达式可以转换为NFA;它们都是表达常规语言的方式。
其次,根据德莫根定律,
因此,这些是计算两个RegEx交集的步骤:
一些消息来源:
答案 1 :(得分:6)
答案 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联盟
不要在交叉点上工作,而是假设您对以下正则表达式的并集感兴趣,即与这些正则表达式匹配的正则表达式:
这是通过交替|
运算符完成的:
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"]