为什么这两个正则表达式表现不同?

时间:2014-03-05 22:01:29

标签: regex perl

为什么以下两个正则表达式的行为不同?

$millisec = "1391613310.1";
$millisec =~  s/.*(\.\d+)?$/$1/;

VS

$millisec =~  s/\d*(\.\d+)?$/$1/;

此代码不打印任何内容:

perl -e 'my $mtime = "1391613310.1"; my $millisec = $mtime; $millisec =~  s/.*(\.\d+)?$/$1/;  print "$millisec";'

虽然这会打印字符串的小数部分:

perl -e 'my $mtime = "1391613310.1"; my $millisec = $mtime; $millisec =~  s/\d*(\.\d+)?$/$1/;  print "$millisec";'

2 个答案:

答案 0 :(得分:8)

在第一个正则表达式中,.*占用了字符串末尾的所有内容,因此可选的(.\d+)?无法获取。 $1将为空,因此字符串将替换为空字符串。

在第二个正则表达式中,只从头开始抓取数字,以便\d*在点前停止。 (.\d+)?将选择点,包括尾随数字。

您在括号内使用.\d+,它将匹配任何字符加数字。如果要明确匹配点,则必须使用\.

要使第一个正则表达式与第二个正则表达式相似,您必须编写

$millisec =~  s/.*?(\.\d+)?$/$1/;

这样最初的.*就不会占用所有内容。

答案 1 :(得分:1)

贪婪。

Perl的正则表达式引擎将与每个术语尽可能匹配,然后再继续下一学期。因此.*(.\d+)?$ .*匹配整个字符串,(.\d)?匹配任何内容,因为它是可选的。

\d*(.\d+)?$只能与点匹配,因此必须将.1(.\d+)?匹配