【问题标题】:Perl Regex - Print the matched valuePerl Regex - 打印匹配的值
【发布时间】:2020-08-05 20:39:31
【问题描述】:

打印匹配值的 perl 正则表达式是什么?例如,我想从此字符串打印195

"2011-04-11 00:39:28,736::[main]::INFO (Main.java:73) Test.Main::main() Total Successful Transactions = 195".

我该怎么做?提前致谢

【问题讨论】:

    标签: regex perl


    【解决方案1】:

    您可以在正则表达式中使用括号来捕获子字符串。捕获的组存储在 $1、$2 等中。示例:

    while (<>) {
        if (/Total Successful Transactions = (\d+)/) {
            print "$1\n";
        }
    }
    

    或者,稍微短一点:

    while (<>) {
        print "$1\n" if /Total Successful Transactions = (\d+)/;
    }
    

    您还可以利用列表上下文中的匹配运算符 (//) 返回由组匹配的列表:

    $\ = '\n'; # Output newline after each print.
    while (<>) {
        print for /Total Successful Transactions = (\d+)/;
    }
    

    这让您可以编写一个紧凑的单行(-l 选项自动为每个打印添加换行符等):

    perl -lne 'print for /Total Successful Transactions = (\d+)/'
    

    【讨论】:

      【解决方案2】:

      只是想以不同的方式重新构建以前的答案;请注意,在这种情况下:

      $ perl -e '$str="the variable Xy = 3 in this case"; print $str =~ /Xy = 3/;'
      1 
      

      ...我们得到 1 被打印出来 - 就像“是的,我有一个匹配”。如果我们想返回匹配的文本部分,正如@markusk 指出的那样,“在正则表达式中使用括号来捕获子字符串”:

      $ perl -e '$str="the variable Xy = 3 in this case"; print $str =~ /(Xy = 3)/;'
      Xy = 3
      

      但是,请注意,在捕获时使用此习语连接字符串时可能会遇到问题:

      $ perl -e '$str="the variable Xy = 3 in this case"; print $str =~ /Xy = 3/ . "\n";' 
      1 # OK
      $ perl -e '$str="the variable Xy = 3 in this case"; print $str =~ /(Xy = 3)/ . "\n";' 
      1 # NOT OK
      

      ...所以在这种情况下最好将事情分开:

      $ perl -e '$str="the variable Xy = 3 in this case"; print $str =~ /(Xy = 3)/ ; print "\n";'
      Xy = 3 # OK again
      

       

      但是,如果我们想要捕获“某物”,比如说一个数字 - 那么,由于我们使用括号,我们会自动返回与该习语匹配的内容(而不是整个“搜索”字符串):

      $ perl -e '$str="the variable Xy = 3 in this case"; print $str =~ /Xy = (\d)/ ; \
      print "\n";'
      3
      

      ...因此,要完整捕获搜索到的字符串,我们应该将其再次用括号括起来:

      $ perl -e '$str="the variable Xy = 3 in this case"; print $str =~ /(Xy = (\d))/ ; \
      print "\n";'
      Xy = 33
      

      .... 但是,我们没有得到预期的结果,因为现在有两个匹配项,$1$2;显然成语“print $str =~ /.../”输出所有匹配项(在本例中为“$1$2”)。

      所以为了在这个嵌套匹配的情况下只获取搜索到的字符串,我们现在明确指定只$1

      $ perl -e '$str="the variable Xy = 3 in this case"; $str =~ /(Xy = (\d))/ ; \
      print "$1 \n";'
      Xy = 3 
      

      编辑 2013 年 10 月:通过 Assign one of multiple regex matches to variable as Perl one-liner (dereference array?) - 这也可以用于单班轮:

      $ perl -e '$str="the variable Xy = 3 in this case"; \
      print ( ( $str =~ /(Xy = (\d))/ )[1] ); print "\n";'
      3
      

      ...但是,请注意,print 需要第二组括号,以便直接使用返回的正则表达式(匿名?)数组。

       

      最后,在多行上下文中,确保首先将整个文件/文本“啜”成一个字符串;然后使用/s(单行模式=换行匹配)和/g(全局/多个匹配)-最后,确保匹配表达式在while循环中,以便遍历所有匹配:

      $ echo "some data
      IN
      123
      OUT
      some more data
       is about to follow:
      IN
      256
      OUT
      done with data
      out" | perl -e '$str = do { local $/; <> }; while ($str =~ /(IN(.*?)OUT)/sg) { print "$1\n"} '
      
      IN
      123
      OUT
      IN
      256
      OUT
      

      嗯,希望这对某人有所帮助,
      干杯!

      【讨论】:

      • 吞咽整个文件对于大型输入可能会很昂贵。另一种方法是使用范围运算符:perl -ne 'print if /IN/../OUT/'
      【解决方案3】:

      怎么样:

      print $string =~ /Total Successful Transactions = (\d+)/;
      

      您实际上很少需要使用$1 和朋友。

      【讨论】:

        【解决方案4】:
        /(\d+$)/;
        print $1;
        

        我猜你只是想要号码195。对吧?

        【讨论】:

          【解决方案5】:
          my $str = '"2011-04-11 00:39:28,736::[main]::INFO (Main.java:73) Test.Main::main() Total Successful Transactions = 195".';
          
          $str =~ /Total Successful Transactions = (\d+)/;
          print $1; 
          

          195 将存储在 $1 中

          【讨论】:

            【解决方案6】:

            检查". 之前的最后一位数字。

            #!/usr/bin/env perl
            
            use strict;
            use warnings;
            
            my $string = q{"2011-04-11 00:39:28,736::[main]::INFO (Main.java:73) Test.Main::main() Total Successful Transactions = 195".};
            my ($number) = $string =~ m{ (\d+) " \. \z}x;
            
            print "Matched number: $number\n" if defined $number;
            

            【讨论】:

            • 应该检查匹配是否失败(将 $number 设置为 undef)。另外,您说“最后”,但没有实现。
            • daxim:谢谢。 ysth:谢谢你让我知道。这是一个错过。我已经编辑了我的答案。
            【解决方案7】:

            @markusk 接受的答案的命令行版本非常紧凑:

            perl -ne '/Total Successful Transactions = (\d+)/ && print "$1\n";'
            

            【讨论】:

              【解决方案8】:

              像这样:

              if ("2011-04-11 00:39:28,736::[main]::INFO (Main.java:73) Test.Main::main() Total Successful Transactions = 195" =~ /(\d+)$/) {
                  print $1;
              }
              

              匹配后,匹配的组将以 $1..$n 的形式提供。

              【讨论】:

              • 谢谢,但可以说打印字符串中存在“成功交易”的值(数字)。