使用正则表达式匹配任意顺序的两个单词

6

我花了一些时间学习正则表达式,但我仍然不明白以下技巧如何工作,可以匹配不同顺序的两个单词

import re
reobj = re.compile(r'^(?=.*?(John))(?=.*?(Peter)).*$',re.MULTILINE)

string = '''
John and Peter
Peter and John
James and Peter and John
'''
re.findall(reobj,string)

result

[('John', 'Peter'), ('John', 'Peter'), ('John', 'Peter')]

enter image description here

(https://www.regex101.com/r/qW4rF4/1)

我知道(?=.* )这部分被称为正向预查,但它在这种情况下是如何工作的?

有什么解释吗?


有关向前查看的解释有很多。也许你应该阅读其中一些,而不是要求我们为你写另一个解释。(换句话说:这是一个关于一个被广泛记录和解释的主题的非常基本的问题。我理解对于初学者来说,这个特性可能不是立即显而易见的,但在技术层面上,已经有了各种各样的解释。) - Tomalak
我已经阅读了一些关于“正向先行断言”的教程,但我不记得有任何解释。你能提供一些有用的链接吗? - Aaron
http://www.regular-expressions.info/lookaround.html - Tomalak
谢谢,但我已经读了那个页面几次了。但仍然不知道它如何能够匹配任意顺序。 - Aaron
1
在那个页面上,有这样一句话:“它们不会消耗字符串中的字符,只是断言是否可能匹配。”“.*$”部分是不必要的。 - Avinash Raj
谢谢@AvinashRaj,这看起来更清晰了。 - Aaron
1个回答

2
它不以任意顺序匹配。这里的捕获是由.*完成的,它会消耗掉任何出现在它面前的字符。而正向先行断言则是一个断言。你有两个先行断言,它们相互独立。每个都做出一个单词的断言。所以最终你的正则表达式像这样工作:
1)(?=.*?(John))===字符串中应该有一个John。只是一个断言,不会消耗任何字符。
2)(?=.*?(Peter))===字符串中应该有一个Peter。只是一个断言,不会消耗任何字符。
3).*===如果断言通过,则消耗所有字符。
所以你看到这里的顺序并不重要,重要的是断言应该通过

谢谢vks,我有点开始理解它的含义了。 - Aaron
1
@Aaron的assertions是独立的。它们不验证顺序。希望你不会感到困惑,对这里发生的事情更加清楚。 - vks
简化为 (?=.*John)(?=.*Peter).* - Hartmut Pfarr
@HartmutPfarr?这样会更快。 - vks

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接