据我所知,|
在交替尝试不同的子模式并匹配第一个可能的选项。只要有多个组,当其中一个子模式为空时,后面的组会出现意外行为,并给予优先权。
示例: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', '')
。
关于为什么模式不能按照我的预期工作的解释将受到赞赏,但这不是我主要关注的问题。提前谢谢!
答案 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字匹配为第一个单词,我认为这不会起作用。我还在努力解决这个问题。