比较不同文件中的第一列

比较不同文件中的第一列

我想将一个文件与同一目录中的其他文件进行比较。

file1.txt包含:

move 34#123#    
get 11#278    
put 33#29#567#23

file1.txt应与文件1.txt和进行比较2.txt

1.txt包含:

move 11    
put 34    
run 13

2.txt包含:

get 14    
move 66

我需要的结果是这样的:

move 2    
get 1    
put 1

我怎样才能做到这一点?

答案1

这是一个awk解决方案:

$ awk 'FNR==NR{a[$1];next}($1 in a){++a[$1]}
    END{for(i in a){print i" "a[i]}}' file1.txt 1.txt 2.txt
put 1
get 1
move 2

解释

  • FNR==NR{a[$1];next}:在处理时,我们标记关联数组中file1.txt出现的情况。$1a
  • ($1 in a){++a[$1]}:在处理1.txt和时2.txt,我们检查$1关联数组 中是否存在a,如果存在,则将计数加 1。
  • 最后,循环关联数组a,打印键(文件中的第一个字段)及其值(1.txt和中出现的次数2.txt)。

这是 中的另一个解决方案perl,具有相同的逻辑:

$ perl -alne '++$i;                  
    if ($. == $i) {
        $h{$F[0]}=0;
        close ARGV if eof;
        next;
    }
    ++$h{$F[0]} if defined $h{$F[0]};
END {
    for (keys %h) {
        print $_." ".$h{$_};
    }
}' file1.txt 1.txt 2.txt
move 2
get 1
put 1

答案2

显示使用各种工具的替代方案,grep, awk, sort, & uniq。当然,它使用了更多工具,但我发现与 AWK 相比,它更容易理解正在发生的事情。

$ for i in 1.txt 2.txt; do grep -f <(awk '{print $1}' $i) file1.txt; done | \
    awk '{print $1}' | sort | uniq -c

例子

$ for i in 1.txt 2.txt; do grep -f <(awk '{print $1}' $i) file1.txt; done | \
    awk '{print $1}' | sort | uniq -c
      1 get
      2 move
      1 put

怎么运行的

这是稍微展开的示例。

$ for i in 1.txt 2.txt; do 
    grep -f <(awk '{print $1}' $i) file1.txt
  done | \
    awk '{print $1}' | sort | uniq -c

for循环遍历我们要匹配的 2 个文件,1.txt并且2.txt.每次循环时,我们都会使用其中一个文件中的第一列作为静态字符串集,grep在目标文件file1.txt.这是执行此操作的行:

$ grep -f <(awk '{print $1}' $i) file1.txt

使用循环中的每个文件运行该命令后,for我们获取所有输出并仅选择其中的第一列:

move
put
move
get

然后我们使用sortuniq来统计我们看到的每种类型的数量。

答案3

这是另一种方法join

join -1 1 -2 2 -o 0 2.1 <(sort -k1,1 file1.txt) <(cut -d ' ' -f1 1.txt 2.txt | sort | uniq -c)

请注意,输出将被排序:

get 1
move 2
put 1

如果您想保留来自file1.txt例如的订单

move 2
get 1
put 1

你可以运行:

join -j2 -o 1.1 0 2.1 <(nl -ba -nrz file1.txt | sort -k2,2) \
<(cut -d ' ' -f1 1.txt 2.txt | sort | uniq -c) | sort -k1 | cut -d ' ' -f2-

相关内容