Regex 环顾会影响哪些语言可以被正则表达式匹配吗?
现代正则表达式引擎中有一些功能,允许您匹配没有该功能无法匹配的语言。例如,以下使用反向引用的正则表达式匹配由重复自身的单词组成的所有字符串的语言:Regex 环顾会影响哪些语言可以被正则表达式匹配吗?,regex,lookbehind,lookahead,lookaround,Regex,Lookbehind,Lookahead,Lookaround,现代正则表达式引擎中有一些功能,允许您匹配没有该功能无法匹配的语言。例如,以下使用反向引用的正则表达式匹配由重复自身的单词组成的所有字符串的语言:(.+)\1。此语言不是常规语言,无法由不使用反向引用的正则表达式匹配 lookaround是否也会影响正则表达式可以匹配哪些语言?也就是说,是否有任何语言可以使用lookaround进行匹配,而其他语言则无法进行匹配?如果是这样的话,这是适用于所有类型的环视(消极或积极的向前环视或向后环视)还是仅适用于其中一些类型?对于您提出的问题,即是否可以通过环
(.+)\1
。此语言不是常规语言,无法由不使用反向引用的正则表达式匹配
lookaround是否也会影响正则表达式可以匹配哪些语言?也就是说,是否有任何语言可以使用lookaround进行匹配,而其他语言则无法进行匹配?如果是这样的话,这是适用于所有类型的环视(消极或积极的向前环视或向后环视)还是仅适用于其中一些类型?对于您提出的问题,即是否可以通过环视扩展的正则表达式来识别比正则语言更大的一类语言,答案是否定的 证明相对简单,但将包含lookarounds的正则表达式转换为不包含lookarounds的正则表达式的算法比较麻烦 第一:请注意,您总是可以对正则表达式求反(在有限的字母表上)。给定一个识别表达式生成的语言的有限状态自动机,您可以简单地将所有接受状态交换为非接受状态,以获得一个FSA,该FSA可以准确识别该语言的否定,其中有一系列等价的正则表达式 第二:因为正则语言(以及正则表达式)在否定条件下是封闭的,所以它们在交集条件下也是封闭的,因为根据德摩根定律,交集B=neg(neg(A)union neg(B))。换句话说,给定两个正则表达式,您可以找到另一个同时匹配这两个正则表达式的正则表达式 这允许您模拟环视表达式。例如,u(?=v)w只匹配将匹配uv和uw的表达式 对于负前瞻,您需要与集合论A\B等价的正则表达式,它只是一个交集(neg B)或等价的neg(neg(A)并集B)。因此,对于任何正则表达式r和s,您都可以找到一个正则表达式r-s,它与那些与r匹配但与s不匹配的表达式相匹配。在负前瞻术语中:u(?!v)w只匹配那些匹配uw-uv的表达式 环视之所以有用,有两个原因 首先,因为对正则表达式的否定可能会导致一些不整洁的东西。例如
q(?!u)=q($|[^u])
其次,正则表达式不仅仅是匹配表达式,它们还使用字符串中的字符——或者至少我们喜欢这样认为。例如,在python中,我关心.start()和.end(),因此:
>>> re.search('q($|[^u])', 'Iraq!').end()
5
>>> re.search('q(?!u)', 'Iraq!').end()
4
第三,我认为这是一个非常重要的原因,正则表达式的否定不能很好地超越串联。neg(a)neg(b)与neg(ab)不是一回事,这意味着您无法在查找它的上下文之外转换查找-您必须处理整个字符串。我想这会让人们感到不愉快,也会破坏人们对正则表达式的直觉
我希望我已经回答了你的理论问题(现在已经很晚了,所以如果我不清楚,请原谅我)。我同意一位评论员的观点,他说这确实有实际应用。我在尝试刮取一些非常复杂的网页时遇到了非常类似的问题
编辑
我为没有说得更清楚表示歉意:我不相信你能通过结构归纳法证明正则表达式+环顾法的规律性,我的u(?!v)w示例就是这个示例,一个简单的示例。结构归纳法不起作用的原因是,环顾四周的人以一种非组合的方式行事——这正是我试图在上面阐述的关于否定的观点。我怀疑任何直接的正式证据都会有很多混乱的细节。我试着想一个简单的方法来展示它,但是我想不出一个简单的方法
为了说明如何使用Josh的第一个^([^a]|(?=…b))*$
示例,这相当于所有州都接受的7州DFSA:
A - (a) -> B - (a) -> C --- (a) --------> D
Λ | \ |
| (not a) \ (b)
| | \ |
| v \ v
(b) E - (a) -> F \-(not(a)--> G
| <- (b) - / |
| | |
| (not a) |
| | |
| v |
\--------- H <-------------------(b)-----/
换句话说,通过消除lookarounds得到的任何正则表达式通常都会更长、更混乱
回应Josh的评论——是的,我确实认为证明等效性的最直接方法是通过FSA。这种混乱的原因在于,通常构造FSA的方法是通过一个非确定性机器——它更容易将u | v表示为一个简单的机器,该机器由u和v的机器构造而成,并带有一个ε过渡到它们两个的过程。当然,这相当于确定性机器,但有状态指数膨胀的风险。然而,通过确定性机器进行否定要容易得多
一般证明将涉及两台机器的笛卡尔积,并选择希望在每个点保留的状态,以插入环视。上面的例子在某种程度上说明了我的意思
我为没有提供建筑而道歉
进一步编辑:
我发现了一个描述了一个算法,该算法用于从使用lookarounds扩充的正则表达式生成DFA。这很好,因为作者以一种显而易见的方式扩展了NFA-e的概念,即“标记的ε转换”,然后解释了如何将这种自动机转换为DFA
我认为这样做是一种方式,但我很高兴有人写了它。我想不出这么简洁的东西。我感觉这里有两个截然不同的问题:
- Regex引擎是否更多地包含“环顾”功能 比没有的正则表达式引擎强大李>
- “环顾四周”
使正则表达式引擎能够解析
比
^(a([^a](ab)*[^a]|a(ab|[^a])*b)b)*$