在具有多个组的python正则表达式子模式中优先使用空字符串

时间:2015-10-22 21:24:22

标签: python regex python-2.7 python-3.x

据我所知,|在交替尝试不同的子模式并匹配第一个可能的选项。只要有多个组,当其中一个子模式为空时,后面的组会出现意外行为,并给予优先权。

示例:re.search("(ab|a|).*(as|a|).*(qwe|qw|)", "abcde asdfg qwerty").groups()返回:('ab', '', '')

如果删除了空选项re.search("(ab|a|).*(as|a).*(qwe|qw)", "abcde asdfg qwerty").groups()结果为('ab', 'as', 'qwe'),则符合预期。

我感兴趣的是获得第二个结果的方法,并且能够匹配abc qwerty之类的字符串并获得('ab', '', 'qwe')abcd asd并获得('ab', 'as', '')

关于为什么模式不能按照我的预期工作的解释将受到赞赏,但这不是我主要关注的问题。提前谢谢!

3 个答案:

答案 0 :(得分:1)

您获得该中间群组.*的原因是贪婪的。它会查看字符串中的所有字符并消耗所有字符。

你可能想要这样的东西:

(ab|a|).* ?(as|a|).* (qwe|qw|)

如果您准确发布所需内容,可能会更有帮助。我不确定这可能是什么用例,以及是否有更好的方法来编写该正则表达式。

答案 1 :(得分:1)

您的问题的原因是贪婪和空令牌的组合。原因是当模式开始时,它将很乐意匹配字符串开头的ab。所以第一个令​​牌就满足了。现在下一个标记是贪婪的点。这将消耗目标字符串中的所有剩余字符。这满足了这个标记。下一个标记是交替。由于贪婪点,因为您位于目标字符串的末尾,因此前两个选项都不能匹配。但是,空令牌可以简单地匹配。这满足了整个群体。下一个标记是另一个贪婪的点。但是,此点需要或更多出现任何字符。因为你在字符串的末尾(因为第一个贪婪的点),所以这个令牌非常满意。最终令牌具有与先前描述的组相同的行为和结果。所以,这个最后的标记再次得到了满足。

答案 2 :(得分:1)

re.match('^(ab|a|)\w*\s*(?:(as|a)\w*|)\w*?\s*(qwe|qw|)',s) #s is your string

这是我能想到的最好的。正如Kenneth K.所说,在匹配空匹配时,有一种贪婪的令牌和非贪婪的令牌的微不足道的组合。解决这个问题的方法是不要使用.*,因为它很容易就只能吃掉它路径上的所有东西。相反,如果可能的话,这基本上会寻找下一个单词和匹配,如果它不能正常通过。

你想要的和我所拥有的之间的唯一区别应该是,如果第二个(' as | a')字符串不存在,那么该对象将是{而不是空白字符串{1}}而不是None,但您可以解决这个问题

试验:

''

如果你想让第三个元素出现>>> s = 'abasdf asdf qwert' >>> re.match('^(ab|a|)\w*\s*(?:(as|a)\w*|)\w*?\s*(qwe|qw|)',s).groups() ('ab', 'as', 'qwe') >>> s = 'abab asf qwert' >>> re.match('^(ab|a|)\w*\s*(?:(as|a)\w*|)\w*?\s*(qwe|qw|)',s).groups() ('ab', 'as', 'qwe') >>> s = 'abab qwert' >>> re.match('^(ab|a|)\w*\s*(?:(as|a)\w*|)\w*?\s*(qwe|qw|)',s).groups() ('ab', None, 'qwe') >>> s = 'abab asfq' >>> re.match('^(ab|a|)\w*\s*(?:(as|a)\w*|)\w*?\s*(qwe|qw|)',s).groups() ('ab', 'as', '') ,你也可以使用re.match('^(ab|a|)\w*\s*(?:(as|a)\w*|)\w*?\s*(?:(qwe|qw)\w*|)',s).groups()

注意:如果您想将as或qwe字匹配为第一个单词,我认为这不会起作用。我还在努力解决这个问题。