我想将一个文件与同一目录中的其他文件进行比较。
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
出现的情况。$1
a
($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
然后我们使用sort
和uniq
来统计我们看到的每种类型的数量。
答案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-