我正在尝试匹配句子中的可选(可能存在)短语:
perl -e '$_="word1 word2 word3"; print "1:$1 2:$2 3:$3\n" if m/(word1).*(word2)?.*(word3)/'
Output:
1:word1 2: 3:word3
我知道第一个“.*”是贪婪的并将所有内容匹配到“word3”。使其变得非贪婪并没有帮助:
perl -e '$_="word1 word2 word3"; print "1:$1 2:$2 3:$3\n" if m/(word1).*?(word2)?.*(word3)/'
Output:
1:word1 2: 3:word3
这里似乎存在利益冲突。我本以为 Perl 会匹配 (word2)?如果可能的话,仍然满足非贪婪的.*?。至少这是我对“?”的理解。 Perl 正则表达式页面显示“?”匹配 1 次或 0 次,那么它不应该更喜欢匹配一次而不是匹配 0 次吗?
更令人困惑的是,如果我捕获 .*?:
perl -e '$_="word1 word2 word3"; print "1:$1 2:$2 3:$3 4:$4\n" if m/(word1)(.*?)(word2)?.*(word3)/'
Output:
1:word1 2: 3: 4:word3
这里的所有组都是捕获组,所以我不知道为什么它们是空的。
只是为了确保词间空间没有被捕获:
perl -e '$_="word1_word2_word3"; print "1:$1 2:$2 3:$3 4:$4\n" if m/(word1)(.*?)(word2)?.*(word3)/'
Output:
1:word1 2: 3: 4:word3
鉴于唯一未捕获的匹配是 word2 和 word3 之间的匹配,我只能假设它是进行匹配的匹配。
果然:
perl -e '$_="word1_word2_word3"; print "1:$1 2:$2 3:$3 4:$4 5:$5\n" if m/(word1)(.*?)(word2)?(.*)(word3)/'
Output:
1:word1 2: 3: 4:_word2_ 5:word3
因此,贪婪匹配是向后进行的,Perl 很乐意匹配 word2 的零个(而不是一个)实例。使其变得非贪婪也无济于事。
所以我的问题是:如何编写正则表达式来匹配和捕获句子中可能的短语?我在这里给出的例子很简单;我正在解析的实际句子要长得多,我匹配的句子之间有很多单词,因此我无法假设中间文本的任何长度或组成。
非常感谢,
斯科特