我的作业比标题更深入,但标题是我的主要问题。这是作业:
编写一个perl脚本,该脚本将grep文件/目录列表中所有常规文件中出现的所有正则表达式,以及文件/目录列表中目录下的所有常规文件。 如果文件不是TEXT文件,则应首先通过unix命令字符串(无开关)操作该文件,并搜索结果行。如果-l开关只给出了应该打印包含正则表达式的文件的文件名,每行一个。在这种情况下,文件名最多应出现一次。如果没有给出-l开关,那么应该打印所有匹配的行,每行都按文件名和冒号在同一行上进行。从命令行调用示例:
plgrep'ba + d'file1 dir1 dir2 file2 file3 dir3
这是我的代码:
#!/usr/bin/perl -w
use Getopt::Long;
my $fname = 0;
GetOptions ('l' => \$fname);
$pat = shift @ARGV;
while (<>) {
if (/$pat/) {
$fname ? print "$ARGV\n" : print "$ARGV:$_";
}
}
到目前为止,除了读取非文本文件并在使用-l开关时打印出重复的文件名之外,代码执行了它应该执行的所有操作。以下是在命令行中输入以下内容后输出的示例:plgrep'ba + d'file1 file2
哪个完美! 但是当我使用-l开关只打印出文件名时,这就是我在命令行输入以下命令后得到的:plgrep -l'ba + d'file1 file2
如何摆脱这些重复项,只打印出来:
我试过了:
$pat = shift @ARGV;
while (<>) {
if (/$pat/) {
$seen{$ARGV}++;
$fname ? print "$ARGV\n" unless ($seen{$ARGV} > 1); : print "$ARGV:$_";
}
}
但是当我尝试在没有-l开关的情况下运行它时我只得到:
我也尝试过:
$ fname?打印“$ ARGV \ n”除非($ ARGV&gt; 1):打印“$ ARGV:$ _”;
但是我一直在plgrep第17行,“$ ARGV \ n”附近得到语法错误,除非“
如果有人可以帮我解决我的重复问题以及作业的斜体部分,我会非常感激。我甚至不知道从哪个斜体开始。
答案 0 :(得分:1)
如果您只打印文件名,则可以在第一次匹配后退出循环(使用last
命令),因为您已经知道文件匹配。通过不扫描文件的其余部分,这也将阻止名称重复打印。
编辑添加:为了这样做,您还需要切换使用<>
来读取文件,而不是从{{1}获取名称和@ARGV
他们正常。
如果您想继续使用open
,则需要观看<>
以查看它何时发生变化(表明您已开始阅读新文件)并保留一个标记以指示当前文件是否已找到任何匹配项。但是,这种方法需要您完整地读取每个文件,这比仅读取每个文件足以知道它是否包含至少一个匹配(即,在第一个匹配后跳到下一个文件)效率低),所以我建议切换到$ARGV
。
答案 1 :(得分:0)
第一个语法问题只是一个额外的分号。
第二个是你只能在句子结尾处使用if / unless作为语句修饰符 - 你不能将它嵌入条件的中间。
$fname ? print "$ARGV\n" unless ($seen{$ARGV} > 1); : print "$ARGV:$_";
变为:
next if $seen{$ARGV} > 1;
print $fname ? "$ARGV\n" : "$ARGV:$_";