【问题标题】:How does this perl regex work?这个 perl 正则表达式是如何工作的?
【发布时间】:2013-01-31 11:33:01
【问题描述】:

我有一个小的正则表达式可以将整数值拆分为 1000,我只是想知道它是如何工作的。

这是一个 perl 代码。

$intval = 10000;
$intval =~ s/([+-]?\d)(?=(\d{3})+(?!\d))/$1,/go;
print $intval;

【问题讨论】:

  • 您可以使用YAPE::Regex::Explain,它会为给定的 RE 输出带有 cmets 的细分。
  • 感谢您的信息。下次我很想使用那个库。

标签: regex perl


【解决方案1】:

(...) 任何正常的括号集都是一个捕获组,可以在正则表达式匹配后引用,使用特殊变量$1$2 等。

[+-]? 括号创建一个字符组,意思是“匹配这些字符中的任何一个”。 ? 表示“匹配零次或一次”。因此,这允许在匹配开始时使用单个 + 或 -。

\d 匹配单个数字。

(?=...) 这是一个前瞻性。它将要求模式中包含的所有内容都匹配,但不包括在输出“匹配”中。它也不会将字符串中的位置向前移动(这意味着使用前瞻时匹配可以重叠)。

(\d{3})+ 匹配一组或多组三位数。

(?!\d)匹配的内容后面不能跟其他数字。

/$1,/ 用第一个捕获组替换匹配的内容(请记住,这不包括前瞻部分,因为这不算作匹配的一部分),后跟逗号。

go 这些标志是设置正则表达式行为的选项:

  • g 表示它会重复直到找到并替换所有匹配项。
  • o 是一种优化,告诉解释器只编译一次模式,但它在很大程度上已经过时并且在这种情况下完全没有区别,因为没有任何内容被插入到模式中。

因此,此正则表达式将替换单个数字,后跟多个是三的倍数的数字,该数字后跟逗号。它反复运行,找到所有匹配项。这样做的效果是插入逗号作为千位分隔符。

一个小问题:[+-]? 部分完全没有必要。因为正则表达式对数字前面的内容没有要求,所以即使删除了这部分,带有 + 或 - 的数字也可以正常工作。

【讨论】:

    【解决方案2】:

    任何时候你有这样的疑问,简单的出路,使用Yape::Regex::Explain

    #!perl -w
    use strict;
    use YAPE::Regex::Explain;
    
    print YAPE::Regex::Explain->new(qr/([+-]?\d)(?=(\d{3})+(?!\d))/)->explain();
    

    产生这个

    The regular expression:
    
    (?-imsx:([+-]?\d)(?=(\d{3})+(?!\d)))
    
    matches as follows:
    
    NODE                     EXPLANATION
    ----------------------------------------------------------------------
    (?-imsx:                 group, but do not capture (case-sensitive)
                             (with ^ and $ matching normally) (with . not
                             matching \n) (matching whitespace and #
                             normally):
    ----------------------------------------------------------------------
      (                        group and capture to \1:
    ----------------------------------------------------------------------
        [+-]?                    any character of: '+', '-' (optional
                                 (matching the most amount possible))
    ----------------------------------------------------------------------
        \d                       digits (0-9)
    ----------------------------------------------------------------------
      )                        end of \1
    ----------------------------------------------------------------------
      (?=                      look ahead to see if there is:
    ----------------------------------------------------------------------
        (                        group and capture to \2 (1 or more times
                                 (matching the most amount possible)):
    ----------------------------------------------------------------------
          \d{3}                    digits (0-9) (3 times)
    ----------------------------------------------------------------------
        )+                       end of \2 (NOTE: because you are using a
                                 quantifier on this capture, only the
                                 LAST repetition of the captured pattern
                                 will be stored in \2)
    ----------------------------------------------------------------------
        (?!                      look ahead to see if there is not:
    ----------------------------------------------------------------------
          \d                       digits (0-9)
    ----------------------------------------------------------------------
        )                        end of look-ahead
    ----------------------------------------------------------------------
      )                        end of look-ahead
    ----------------------------------------------------------------------
    )                        end of grouping
    ----------------------------------------------------------------------
    
    1. g 修饰符表示需要进行此模式匹配 全球范围内
    2. o 修饰符指定此模式必须是 编译一次

    结帐perlre modifiers 了解更多关于正则表达式修饰符的信息

    【讨论】:

    • +1 用于演示这个有用的工具。值得一提的是,它只支持 Perl 5.6 之前的正则表达式功能。不过,这不会是 OP 的正则表达式的问题。
    • 谢谢@dan1111 我自己没有意识到,赞成你的评论
    猜你喜欢
    • 2011-03-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-01
    相关资源
    最近更新 更多