1

问题:

如何使用 Python 的正则表达式模块 ( re) 来确定是否已进行匹配,或者是否可以进行潜在匹配?

细节:

我想要一个正则表达式模式,它以正确的顺序搜索单词模式,而不管它们之间是什么。我想要一个函数,Yes如果找到,Maybe如果仍然可以找到匹配项或者No找不到匹配项,则返回。我们正在寻找模式One|....|Two|....|Three,这里有一些示例(注意名称、计数或顺序并不重要,我只关心三个单词One, Twoand Three,中间可接受的单词是John, Malkovich, Stamosand Travolta)。

返回是:

One|John|Malkovich|Two|John|Stamos|Three|John|Travolta

返回是:

One|John|Two|John|Three|John

返回是:

One|Two|Three

返回可能:

One|Two

返回可能:

One

返回否:

Three|Two|One

我知道这些例子不是无懈可击的,所以这就是我为正则表达式获得“是”的条件:

if re.match('One\|(John\||Malkovich\||Stamos\||Travolta\|)*Two\|(John\||Malkovich\||Stamos\||Travolta\|)*Three\|(John\||Malkovich\||Stamos\||Travolta\|)*', 'One|John|Malkovich|Two|John|Stamos|Three|John|Travolta') != None
   return 'Yes'

显然,如果Three|Two|One上面的模式会失败,我们可以 return No,但是我该如何检查这种Maybe情况呢?我想过嵌套括号,就像这样(注意,未经测试)

if re.match('One\|((John\||Malkovich\||Stamos\||Travolta\|)*Two(\|(John\||Malkovich\||Stamos\||Travolta\|)*Three\|(John\||Malkovich\||Stamos\||Travolta\|)*)*)*', 'One|John|Malkovich|Two|John|Stamos|Three|John|Travolta') != None
   return 'Yes'

但我不认为那会做我想做的事。

更多细节:

我实际上并不是在寻找TravoltasMalkovichs(令人震惊,我知道)。我正在匹配 inotify 模式,例如IN_MOVE, IN_CREATE, IN_OPEN,并且我正在记录它们并获取数百个,然后我进入然后寻找特定模式,例如IN_ACCESS... IN_OPEN.... IN_MODIFY,但在某些情况下我没有我不想要在其他人IN_DELETE之后IN_OPEN。我本质上是模式匹配,以使用 inotify 来检测文本编辑器何时变得疯狂,并且他们试图通过执行临时文件交换保存而不是仅仅修改文件来粉碎程序员的灵魂。我不想立即释放这些日志,但我只想在必要时保留它们。Maybe意味着不要删除日志。Yes意味着做某事然后擦除日志,No意味着不做任何事情但仍然擦除日志。因为我将为每个程序设置多个规则(即vimv geditv emacs),所以我想使用一个正则表达式,它更易于阅读,更容易编写,然后创建一个巨大的树,或者正如用户Joel建议的那样,只需使用一个循环

4

2 回答 2

4

我不会为此使用正则表达式。但这绝对是可能的:

regex = re.compile(
    r"""^           # Start of string
    (?:             # Match...
     (?:            # one of the following:
      One()         # One (use empty capturing group to indicate match)
     |              # or
      \1Two()       # Two if One has matched previously
     |              # or
      \1\2Three()   # Three if One and Two have matched previously
     |              # or
      John          # any of the other strings
     |              # etc.
      Malkovich
     |
      Stamos
     |
      Travolta
     )              # End of alternation
     \|?            # followed by optional separator
    )*              # any number of repeats
    $               # until the end of the string.""", 
    re.VERBOSE)

现在,您可以通过检查是否完全匹配来检查 YES 和 MAYBE:

>>> yes = regex.match("One|John|Malkovich|Two|John|Stamos|Three|John|Travolta")
>>> yes
<_sre.SRE_Match object at 0x0000000001F90620>
>>> maybe = regex.match("One|John|Malkovich|Two|John|Stamos")
>>> maybe
<_sre.SRE_Match object at 0x0000000001F904F0>

您可以通过检查是否所有组都参加了比赛(即 are not )来区分 YES 和 MAYBE None

>>> yes.groups()
('', '', '')
>>> maybe.groups()
('', '', None)

如果正则表达式根本不匹配,那对您来说就是“否”:

>>> no = regex.match("Three|Two|One")
>>> no is None
True
于 2012-05-19T22:21:43.793 回答
3

有些人在遇到问题时会想“我知道,我会使用正则表达式”。现在他们有两个问题。- 杰米扎温斯基

也许像这样的算法会更合适。这是一些伪代码。

matchlist.current = matchlist.first()
for each word in input
    if word = matchlist.current
        matchlist.current = matchlist.next() // assuming next returns null if at end of list
    else if not allowedlist.contains(word)
        return 'No'
if matchlist.current = null // we hit the end of the list
    return 'Yes'
return 'Maybe'
于 2012-05-19T22:10:25.553 回答