在文本文件的所有行中查找公共元素

时间:2014-09-10 22:21:51

标签: awk

我有一个文本文件,如:

a b c d e
b c e
d f g e h c

我正在寻找一个简单的AWK,可以在忽略第一个元素的所有行中输出公共元素。所需的输出是:

c e

e c

3 个答案:

答案 0 :(得分:3)

$ cat tst.awk
FNR==1 { for (i=1; i<=NF; i++) common[$i]; next }
{
    for (c in common) {
        present = 0
        for (i=1; i<=NF; i++) {
            if ($i == c) {
                present = 1
            }
        }
        if (!present) {
            delete common[c]
        }
    }
}
END {
    i=0
    for (c in common) {
        printf "%s%s", (++i>1?OFS:""), c
    }
    print ""
}
$ awk -f tst.awk file
c e

如果你真的想跳过每一行的第一个字符,只需将2 for (i=1; i<=NF; i++)个循环更改为从2开始而不是1。

虽然上面被接受但我实际上更喜欢@jaypal的方法(但不是他选择的工具:-)),所以这里是awk的等价物:

$ cat tst.awk
{ delete seen; for (i=1; i<=NF; i++) if (!seen[$i]++) count[$i]++ }
END {
    i=0
    for (c in count)
        if (count[c] == NR)
            printf "%s%s", (++i>1?OFS:""), c
    print ""
}
$
$ awk -f tst.awk file
c e

如果您的awk不支持delete seen,请将其更改为split("",seen)

答案 1 :(得分:3)

perl救援:

perl -lane '
    my %seen;
    map { $total{$F[$_]}++ unless $seen{$F[$_]}++ } 1 .. $#F; 
}{ 
    print join " ", grep { $total{$_} == $. } keys %total
' file
e c

保持滚动%total哈希值,只有当元素对每一行都是唯一的时才会增加元素。 %seen是一个有助于跟踪这些元素的哈希。因此,我们使用my声明为每一行重置它。

END块中,我们只是grep那些价值符合总行数的元素,这意味着它们会在每一行上看到。

命令行选项包括:

  • -l:点击换行符并在print期间将其放回原位。
  • -a:拆分空白行并使用这些值加载数组@F
  • -n:创建一个while(<>) { .. }循环来处理每一行。
  • -e:执行引号后面的代码块。

答案 2 :(得分:1)

另一种perl方法:

perl -lane '
    if ($. == 1) { %intersect = map {$_ => 1} @F; next } 
    %intersect =  map {$_ => 1} grep {$intersect{$_}} @F; 
    END {print join " ", keys %intersect}
' file

结果不会有任何特定的顺序。