【问题标题】:Why do these two regexes behave differently?为什么这两个正则表达式的行为不同?
【发布时间】:2014-03-05 22:01:29
【问题描述】:

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

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

对比

$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";'

【问题讨论】:

  • 顺便说一句,这些不是毫秒; 0.1 秒等于 100 毫秒。
  • 就不能写的更干净点吗?赶上 .1 和 1.1,虽然我不确定你想要小数还是整数。看起来像小数。所以对于所有 '/(\d+.d+)$/$1/;'我喜欢使用内存和使用 '\d' 而不是小数 '/\d+(\.\d+)$/$1/' 的 '[0-9]' ;尽管除了询问为什么它们匹配不同之外,意图有点混乱。
  • 嗨,Alex - 是的,我想要小数点。你的意思是“我是如何写这篇文章的”还是“正则表达式”?你能建议更简单的正则表达式(如果是这样的话)吗? .三重奏 - 你是对的。我没有提到我稍后使用 sprintf 来追加零。

标签: regex perl


【解决方案1】:

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

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

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

要使第一个正则表达式的行为类似于第二个,您必须编写

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

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

【讨论】:

    【解决方案2】:

    贪婪。

    Perl 的正则表达式引擎会在继续下一个术语之前尽可能地匹配每个术语。所以对于.*(.\d+)?$.* 匹配整个字符串,然后(.\d)? 不匹配,因为它是可选的。

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

    【讨论】:

    • 关键是(\.\d+)可选的
    • 嗨 Borodin - 为什么 "\d*" 不是贪婪的,而 ".*" 是贪婪的?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-27
    • 1970-01-01
    • 2018-08-24
    • 1970-01-01
    相关资源
    最近更新 更多