我是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
[^\
为什么不按顺序打印这些行?由于“stuff”行会在文件中稍后出现,所以不应该稍后打印?
为什么打印第二行错误?它应该是“\(([^\
”。它缺少前3个字符。
如果我将正则表达式更改为以下内容:/directory\(([^\)]*)\)/
,则无法输出。唯一的区别是这个词。它应该是找到第二条评论。这是怎么回事?
答案 0 :(得分:1)
use 5.006
有点奇怪...这是一个古老的版本。
您不应构建当前目录下所有位置的所有文件的潜在巨大列表,然后对其进行过滤。相反,只将所需文件推送到列表中。
特别是对于转义的元字符,正则表达式模式很难快速阅读,因此请使用/x
修饰符在这些模式中插入一些空格。
您不必两次匹配:只需检查&amp;同时捕获。
如果open
失败,请在错误消息中包含原因。
上面的第二个问题没有意义。您似乎希望您的模式与文字字符串file\(([^\)]*)\)/
匹配,但它不能。
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