python补充复杂的正则表达式

时间:2017-03-22 18:54:47

标签: python regex

尝试学习正则表达式,尽管这里有一些很棒的帖子和链接到regEx网站,我有一个案例,我试图破解纯粹的顽固性,无法产生我正在寻找的比赛。要理解它,请考虑以下代码,它允许我们传入字符串和模式列表,并找出模式是匹配列表中的所有项目还是不匹配任何项目:

import re
def matchNone(pattern, lst):
    return not any([re.search(pattern, i) for i in lst])

def matchAll(pattern, lst):
    return all([re.search(pattern, i) for i in lst])

为了帮助进行调试,这个简单的代码允许我们只需将_test添加到函数调用中,并查看传递给最终返回的any()all()函数的内容结果:

def matchAll_test(pattern, lst):
    return [re.search(pattern, i) for i in lst]

def matchNone_test(pattern, lst):
    return ([re.search(pattern, i) for i in lst])

此模式和列表从True生成matchAll()

wordPattern = "^[cfdrp]an$"
matchAll(wordPattern, ['can', 'fan', 'dan', 'ran', 'pan']) # True

表面上的这种模式似乎与matchNone()一起用于扭转模式:

wordPattern = "^[^cfdrp]an|[cfdrp](^an)$"
matchNone(wordPattern, ['can', 'fan', 'dan', 'ran', 'pan']) # True

它会像我们希望的那样返回True。但是这种模式的真正逆转将返回False一个值列表,其中没有一个值与我们的原始列表['can', 'fan', 'dan', 'ran', 'pan']相同,无论我们传入其中的是什么。 (即“匹配除了这5个字之外的任何东西”)

在测试中查看此列表中单词的哪些更改会让我们得到False,我们很快发现该模式不像第一次出现那样成功。如果是的话,matchNone()对于上述列表中没有的任何内容都会失败。

这些排列有助于揭示我的模式测试的缺点:

["something unrelated", "p", "xan", "dax", "ccan", "dann", "ra"]

在我对上述内容的探索中,我尝试了其他排列以及原始列表,使用_test版本的函数并一次更改原始单词上的一个字母,以及修改一个术语或添加一个术语来自于上面的排列。

如果有人能找到原始模式的真实反转,我很乐意看到它,以便我可以从中学习。

帮助您进行调查:

此模式也适用于matchAll()所有单词,但我似乎无法创建其反转:"^(can|fan|dan|ran|pan)$"

感谢你在这方面花费的任何时间。我希望在这里能找到一位注册错误的regEx大师,并提出正确的解决方案。

2 个答案:

答案 0 :(得分:2)

我希望我理解你的问题。这是我找到的解决方案:

^(?:[^cfdrp].*|[cfdrp][^a].*|[cfdrp]a[^n].*|.{4,}|.{0,2})$
  • [^cfdrp].*:如果文字不是以c,f,d,r或p开头而不是匹配
  • [cfdrp][^a].*:文字以c,f,d,r或p开头:如果第二个字符不是a,则匹配
  • [cfdrp]a[^n].*:文字以[cfdrp]a开头:匹配第三个字符不是n。
  • .{4,}:匹配超过3个字符的任何内容
  • .{0,2}:匹配0,1或2个字符的任何内容

等于:

^(?:[^cfdrp].*|.[^a].*|..[^n].*|.{4,}|.{0,2})$

答案 1 :(得分:1)

您要做的是找到补充。为任何正则表达式执行此操作是一个难题。没有内置补充正则表达式。

PPCG上有一个开放challenge来执行此操作。一个comment解释了难度:

  

这是可能的,但是疯狂乏味。您需要将正则表达式解析为NFA(例如Thompson算法),将NFA转换为DFA(powerset构造),完成DFA,找到补码,然后将DFA转换为RE(例如Brzozowski&#39 ; s方法)。即比编写完整的RE引擎稍微难一点!

有些Python库将从正则表达式转换(原始规范指的是"常规语言",它只有文字,"或",和&# 34;明星" - 比你想到[more info here]的正则表达式类型简单到NFA,DFA,补充它,并将其转换回来。这很复杂。

这是一个相关的SO问题:Finding the complement of a DFA?

总之,找到原始正则表达式的结果要简单得多,然后使用布尔否定。