6

我正在尝试从文件句柄中打印重复的行,而不是删除它们或我在其他问题上看到的任何其他问题。我没有足够的 perl 经验来快速做到这一点,所以我在这里问。这样做的方法是什么?

4

4 回答 4

25

使用标准的 Perl 速记:

my %seen;
while ( <> ) { 
    print if $seen{$_}++;
}

作为“单线”:

perl -ne 'print if $seen{$_}++'

更多数据?这打印<file name>:<line number>:<line>

perl -ne 'print ( $ARGV eq "-" ? "" : "$ARGV:" ), "$.:$_" if $seen{$_}++'

解释%seen

  • %seen声明一个哈希。对于输入中的每个唯一行(while(<>)在这种情况下来自)$seen{$_},在哈希中都有一个标量槽,由行的文本命名(这就是在大括号$_中所做的)。{}
  • 使用后缀增量运算符 ( x++) 我们为表达式取值,记住在表达式之后递增它。因此,如果我们没有“看到”该行$seen{$_}是未定义的——但是当强制进入这样的数字“上下文”时,它被视为 0——和false
  • 然后它增加到 1。

因此,当while开始运行时,所有行都是“零”(如果它有助于您可以将这些行视为“非%seen”)然后,当我们第一次看到一行时,perl将采用未定义的值 - 它失败了if- 并递增标量槽的计数为 1。因此,对于任何未来发生的事件,它都为 1,此时它通过if条件并打印。

现在就像我上面所说的,%seen声明一个哈希,但是strict关闭后,可以在现场创建任何变量表达式。所以 perl 第一次看到$seen{$_}它就知道我正在寻找%seen,它没有它,所以它创建了它。

一个额外的整洁的事情是,最后,如果你愿意使用它,你可以计算每行重复了多少次。

于 2011-05-04T13:50:26.517 回答
3

只打印一次副本:

perl -ne "print if $seen{$_}++ == 1"
于 2011-11-02T20:08:01.643 回答
3

尝试这个

#!/usr/bin/perl -w
use strict;
use warnings;

my %duplicates;
while (<DATA>) {
    print if !defined $duplicates{$_};
    $duplicates{$_}++;
}
于 2011-05-04T13:50:32.160 回答
1

如果你有一个类 Unix 系统,你可以使用uniq

uniq -d foo

或者

uniq -D foo

应该做你想做的。更多信息:man uniq

于 2011-05-04T16:07:37.963 回答