【问题标题】:How to print without duplicates with perl?如何用perl打印不重复?
【发布时间】:2013-02-18 04:56:46
【问题描述】:

我的作业比标题更深入一点,但标题是我的主要问题。这是作业:

编写一个 perl 脚本,该脚本将对文件/目录列表中的所有常规文件以及文件/目录列表中目录下的所有常规文件中所有出现的正则表达式进行 grep。 如果文件不是 TEXT 文件,则应首先通过 unix 命令 strings 操作该文件(无开关)并搜索结果行。 如果 -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

  • file1:我的狗坏了。
  • file1:我的狗非常棒。
  • file2:我的吉他不好。
  • file2:虽然吉他弹得不好,但弹起来还是很有趣的!

这是完美的! 但是当我使用 -l 开关只打印文件名时,这是在命令行上输入以下内容后得到的:plgrep -l 'ba+d' file1 file2

  • 文件1
  • 文件1
  • 文件2
  • 文件2

如何去除那些重复的,让它只打印出来:

  • 文件1
  • 文件2

我试过了:

$pat = shift @ARGV;
while (<>) {
    if (/$pat/) {
        $seen{$ARGV}++;
        $fname ? print "$ARGV\n" unless ($seen{$ARGV} > 1); : print "$ARGV:$_";
    }
}

但是当我尝试在没有 -l 开关的情况下运行它时,我只会得到:

  • file1:我的狗坏了。
  • file2:我的吉他不好。

我也试过了:

$fname ?打印 "$ARGV\n" 除非 ($ARGV > 1) : 打印 "$ARGV:$_";

但我在 plgrep 第 17 行,靠近 ""$ARGV\n" 除非"

如果有人可以帮助我解决我的重复问题以及作业的斜体部分,我将不胜感激。我什至不知道从那个斜体部分开始。

【问题讨论】:

    标签: perl printing no-duplicates


    【解决方案1】:

    如果您只打印文件名,您可以在第一次匹配后退出循环(使用last 命令),因为您已经知道文件匹配。通过不扫描文件的其余部分,这也将防止名称被重复打印。

    编辑添加:为了做到这一点,您还需要从使用 &lt;&gt; 读取文件切换为从 @ARGV 和 @987654324 获取名称正常@他们。

    如果您想继续使用&lt;&gt;,则需要观察$ARGV 以查看它何时更改(表明您已开始读取新文件)并保留一个标志以指示当前文件是否是否已找到任何匹配项。但是,这种方法需要您完整读取每个文件,这比仅读取每个文件的足够多以知道它是否包含至少一个匹配项(即,在第一个匹配项后跳到下一个文件)效率要低),所以我建议改用open

    【讨论】:

      【解决方案2】:

      第一个语法问题只是多了一个分号。

      第二个是您只能在语句末尾使用 if/unless 作为语句修饰符 - 您不能以这种方式将其嵌入到条件中间。

      $fname ? print "$ARGV\n" unless ($seen{$ARGV} > 1); : print "$ARGV:$_";
      

      变成:

      next if $seen{$ARGV} > 1;
      print $fname ? "$ARGV\n" : "$ARGV:$_";
      

      【讨论】:

      • 这和我上面写的一样。当我不使用 -l 开关时,它会删除文件名重复但如果已经在一个文件中找到字符串,它仍然会删除字符串。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-02-25
      • 1970-01-01
      • 2012-06-05
      • 1970-01-01
      • 1970-01-01
      • 2018-04-25
      • 1970-01-01
      相关资源
      最近更新 更多