为什么perl中的这个正则表达式适用于一个单词而不适用于另一个单词?

时间:2017-08-24 18:26:46

标签: regex perl

我是perl的新手,所以如果我的问题显而易见,请原谅。我做了一个小的perl脚本,只是检查自己提取我正在寻找的特定子串,我得到的结果是我无法解释的。这是脚本:

use 5.006;
use strict;
use warnings;
use File::Find;

my @files;
find( 
    sub { push @files, $File::Find::name unless -d; }, 
    "."
);

my @filteredfiles = grep(/.pl/, @files);

foreach my $fileName (@filteredfiles)
{
open (my $fh, $fileName) or die "Could not open file $fileName";

while (my $row = <$fh>)
{
    chomp $row;
    if ($row =~ /file/)
    {
        my ($substring) = $row =~ /file\(([^\)]*)\)/;
        print "$substring\n" if $substring;
    }
}

close $fh;
}

# file(stuff)
# directory(stuff)

现在,当我运行它时,我得到以下输出:

stuff
[^\
  1. 为什么不按顺序打印这些行?由于“stuff”行会在文件中稍后出现,所以不应该稍后打印?

  2. 为什么打印第二行错误?它应该是“\(([^\”。它缺少前3个字符。

  3. 如果我将正则表达式更改为以下内容:/directory\(([^\)]*)\)/,则无法输出。唯一的区别是这个词。它应该是找到第二条评论。这是怎么回事?

1 个答案:

答案 0 :(得分:1)

    如果你刚刚开始学习Perl,那么
  1. use 5.006有点奇怪...这是一个古老的版本。

  2. 您不应构建当前目录下所有位置的所有文件的潜在巨大列表,然后对其进行过滤。相反,只将所需文件推送到列表中。

  3. 特别是对于转义的元字符,正则表达式模式很难快速阅读,因此请使用/x修饰符在这些模式中插入一些空格。

  4. 您不必两次匹配:只需检查&amp;同时捕获。

  5. 如果open失败,请在错误消息中包含原因。

  6. 上面的第二个问题没有意义。您似乎希望您的模式与文字字符串file\(([^\)]*)\)/匹配,但它不能。

  7. use strict;
    use warnings;
    use File::Find;
    
    my @files;
    
    find(
        sub {
            return if -d;
            return unless / [.] pl \z/x;
            push @files, $File::Find::name;
        },
        '.',
    );
    
    for my $file ( @files ) {
        open my $fh, '<', $file
            or die "Could not open file $file: $!";
    
        while (my $line = <$fh>) {
            if (my ($substring) = ($line =~ m{ (?:file|directory) \( ([^\)]*) \) }x)) {
                print "$substring\n";
            }
        }
    
        close $fh;
    }
    
    # file(stuff)
    # directory(other)
    

    输出:

    stuff
    other