我正在努力了解这种背后
我尝试的这个例子不像我预期的那样工作。我想尝试形成一个匹配John
而不是John.
的正则表达式
以下内容:
$ perl -e '
my $var = "John.";
if( $var =~ m/J*/) {
print "Matches!\n";
}
'
Matches!
当然与.
匹配并包括$ perl -e '
my $var = "John.";
if( $var =~ m/J*(?<![.])/) {
print "Matches!\n";
}
'
Matches!
。问题如下:
John.
对于后者,我预计正则表达式将匹配my $var = "John. ";
消费&gt;。&lt; (期间)
然后在下一个位置,它会向后看,并意识到它消耗了一段时间(。)并拒绝匹配
我的理解错了吗?我在这里搞砸了什么?
更新:
John
更新2 :
我的问题不在于如何仅匹配John.
而不是{{1}}
但要理解外观是如何工作的,以及它是否应该在这种情况下起作用。
答案 0 :(得分:4)
*
是量化运算符,而不是占位符。因此A*
表示零个或多个A
个字符。没有任何进一步的背景,这总是匹配,例如, "foo" =~ /J*/
是真的。
你打算写的是/J.*/
,你做了你实际描述过的事情。
现在让我们来看看当我们"John." =~ /(J.*(?<![.]))/
时会发生什么:
J
。.*
,与ohn.
匹配。(?<![.])
,但失败了。.*
,但这次只匹配ohn
。(?<![.])
,即成功。在上面的正则表达式中,我将模式包含在一个捕获组中,我们现在可以读出它:
$ perl -E'"John." =~ /(J.*(?<![.]))/ and say "<$1>" or say "No match"'
<John>
使用字符类而不是断言和.*
量化通常更有效,这样我们就可以避免回溯:
/J[^.]*/
然而,这并不完全等同于上述正则表达式。
答案 1 :(得分:0)
这个正则表达式:
/John(?![.])/
将匹配John
,但不匹配John
。它使用负向look- 提前断言(而不是在后面看)。
如果你想匹配“John”以外的全名,你需要更加具体地说明你在比赛中做了什么和不想做什么,因为J*
会匹配零个或多个J
。
编辑:显然我误读了@ amon帖子的*
。前瞻与后视仍然适用。