
シェルスクリプトを作成していますが、一意の値の結果とその数を一度に1つのファイルにマージしたいと思います。たとえば、次の2つのファイルからデータを読み取る場合(最初の列の数字は一意の数です):
最初のループはデータを読み込みます。
3 Dog
1 Cat
5 Horse
2番目のループでデータを読み取る
1 Dog
3 Cat
1 Horse
2 Goat
私の「カウントファイル」を次のように上書きするように、2番目と1番目のファイルをマージしたいと思います。
2番目のループが完了した後の結果ファイル
4 Dog
4 Cat
6 Horse
2 Goat
データセットが大きく、ファイルをダウンロードするよりもファイルを読み取って削除する方が良いので、これを実行しようとしています(またはファイルがかなり長いため、cat
ファイルをまとめて最後に見つけること)。uniq -c
これを行う方法はありますか?ありがとうございます!
答え1
この方法は、一時awk
ファイルtallytmp
と名前付きの単純な実行回数を合計するために使用されますtally
。sort
2番目のフィールド(-k2
)に2つのカウントファイルをまとめました。
tally
開始するには空のファイルが必要なので、touch tally
繰り返しごとに次のことが行われます。
uniq -c file > tallytmp
sort -k2 tally tallytmp \
|awk '{
if($2==prev){
tot+=$1
}else{
print tot,prev;
tot=$1;pc=$1;prev=$2
}
}END{
print tot,prev
}' > tallyresult
cp tallyresult tally
(続けてawk
スクリプトを1行に入れてください.)
sort|awk
論理的にパイプを直接リダイレクトできるはずですtally
が、sort
それでも使用するため、tallyresult
結果ファイルにコピーする前に2番目の一時ファイルが必要ですtally
。
与えられた2つの反復の出力は実際には次のようになります。
[blank line]
4 Cat
4 Dog
2 Goat
6 Horse
2番フィールドの順序に基づいて順序が混ざっているのにうまく動作します。私はそれを使っていくつかの繰り返しを実行することができました。
答え2
誰かが私の以前の答えに賛成投票したので、当然新しいソリューションを考案しなければなりませんでした!これは2つの理由でより良いです:
- 純粋で
bash
ハッシュテーブルを使用してください。awk
- ジャンクの空白行は表示されません。
- 好きなだけファイルを追加できます
tally
(3つの理由)。 - ファイルが空で
tally
ある可能性があります(4つの理由)。 - 一時ファイルは必要ありません(「それは考えていませんでした」など)。
以下を別の名前で保存してください。tally.sh
#!/bin/bash
# define the associative array tally_table
declare -A tally_table
while read line ; do
k=($line)
[ -n "${k[1]}" ] && (( tot[${k[1]}] += ${k[0]} ))
done <<HERE
$(cat tally $@)
HERE
for i in "${!tally[@]}"; do
echo "${tally[$i]} $i"
done > tally
cat tally
次の行でtally
名前が付けられた新しいレポートファイルを削除して作成してみてください。file
1 Horse
3 Monkey
その後、入力してください。
$ ./tally.sh file
3 Monkey
1 Horse
ここで、newfile
数行の名前で別のレポートを作成します。
5 Horse
2 Pig
そして餌を与えなさい:
$ ./tally.sh newfile
3 Monkey
6 Horse
2 Pig
アイテムHorse
が正しく増加します。もちろん、以前と同様に、順序が一致しません。 (どのようにソートするかはわかりませんが、犬、猫、馬、ヤギの注文可能、またはMonkey
その中の位置。 )