同じディレクトリにある他のファイルとファイルを比較したいです。
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]}
:sumを処理するときに1.txt
連想配列に存在することを2.txt
確認し、存在する場合は数に1を加えます。$1
a
- 最後に、連想配列を繰り返して、
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
ファイルの1つの最初の列を静的文字列セットとして使用します。grep
file1.txt
$ grep -f <(awk '{print $1}' $i) file1.txt
ループ内の各ファイルに対してコマンドを実行した後、すべてのfor
出力を取得し、その中の最初の列のみを選択します。
move
put
move
get
次に、sort
sumを使用して、私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-