【问题标题】:Perl extract matches from listPerl 从列表中提取匹配项
【发布时间】:2011-10-05 18:40:40
【问题描述】:

我对 perl 相当陌生,但对脚本语言不熟悉。我有一个文件,我试图只提取与正则表达式匹配的每一行的一部分。例如,给定文件:

FLAG(123)
FLAG(456)
Not a flag
FLAG(789)

我想提取列表 [123, 456, 789]

正则表达式显然是/^FLAG\((\w+)/。我的问题是,在 perl 中提取这些数据的简单方法是什么?

显然,设置一个循环并进行一堆 =~ 匹配并不难,但我听说过很多关于 perl 的简洁性以及它如何为所有内容提供运算符的信息,所以我想知道是否有巧妙、简单的方法。

另外,您能否为我指出一个好的 perl 参考资料,当机会出现时,我可以在其中找到做其他类似事情的巧妙方法?网上有很多 perl 资源,但其中 90% 太简单了,另外 10% 我似乎在噪音中失去了信号。

谢谢!

【问题讨论】:

    标签: perl


    【解决方案1】:

    我会这样做...你学到了什么新的和/或有用的东西吗?

    my $file_name = "somefile.txt";
    open my $fh, '<', $file_name or die "Could not open file $file_name: $!";
    
    my @list;
    while (<$fh>)
    {
        push @list, $1 if /^FLAG\((\w+)/;
    }
    

    值得指出的地方:

    1. while 循环条件中(并且仅在 while 循环条件中),从文件句柄中读取会将值设置为 $_ 并检查文件是否已自动读取。
    2. 可以通过在语句末尾附加ifunlessforforeachwhileuntil 来修改语句。然后它作为一个条件语句或循环运行。
    3. 您可能知道正则表达式捕获组存储在$1$2 等中,但您可能不知道即使该语句具有if 后缀,该语句也会起作用。 if 首先被评估,所以 push @list, $1 if /some_regex/ 有意义并且会首先进行匹配,在 push 语句中需要它之前分配给 $1

    【讨论】:

      【解决方案2】:

      假设您将所有数据放在一个字符串中:

      my @matches = $data =~ /^FLAG\((\w+)/mg;
      

      /g 修饰符意味着匹配尽可能多的次数,/m 使 ^ 在任何换行符之后匹配(不仅在字符串的开头),并且列表上下文中的匹配返回所有捕获所有这些比赛。

      如果您是逐行读取数据,那么 Platinum Azure 的解决方案就是您想要的解决方案。

      【讨论】:

      • +1 用于考虑单个字符串大小写,这是我没有想到的。
      【解决方案3】:

      map 是你的朋友。

      use strict;
      use warnings;
      use File::Slurp;
      
      my @matches = map { /^FLAG\((\w+)/ } read_file('file.txt');
      

      【讨论】:

      • 大概这需要在内存中拥有file.txt 的全部内容。可能是大文件的问题。 :-)
      • 酷。我不知道应用正则表达式会导致返回第一个匹配项。我想如果你的正则表达式有多个匹配组,那么结果将是一个标量?谢谢!
      • 实际上,我不确定这个是否可行。首先,在标量上下文中,正则表达式返回不匹配的假值和匹配的真值。在列表上下文中,它将返回组(如果使用 g 选项,则返回匹配项),但如果不匹配,它也会返回 undef。对于所有不匹配的行,@matches 不会包含 undef 吗?我认为您需要在此之上添加grep 以防止出现问题。
      猜你喜欢
      • 2020-01-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多