助けてください?私には任務がある。数字を含むテキストを入力しました。たとえば、
beta 1
score 9
something 2
beta 4
something 1
周囲に同じテキストを含むすべての数字を数える必要があります。私の出力は次のとおりです。 (このように「:」を使用してください)
beta:5
something:3
score:9
さらに、スコアを保存する一時ファイルに問題がある可能性があります。mktemp
スクリプトが完了したら削除するために使用する必要があります。助けてくれてありがとう。
ベストアンサー1
入力には常に1行に2つのフィールドが含まれていると仮定します。
GNUユーティリティを使用してdatamash
データをソートし、最初のフィールドでグループ化し、各グループの2番目のフィールドの合計を計算できます。
datamash -s -W --output-delimiter=: groupby 1 sum 2 <file
ここでは、ユーティリティーは連続した空白文字をフィールド区切り文字として扱い、出力区切り文字を対応する文字に設定するように-s
入力をソートします。残りは、最初のフィールドに基づいてグループ化し、各グループの2番目のフィールドの合計を計算するように指示します。-W
--output-delimiter=:
:
datamash
というファイルの問題への入力が与えられると、次のfile
ような出力が生成されます。
beta:5
score:9
something:3
他の多くの方法でもこの問題を解決できます。最も簡単な計算ソリューションは、次のものを使用することですawk
。
awk '{ sum[$1] += $2 } END { for (key in sum) printf "%s:%d\n", key, sum[key] }' file
sum
ここでは、最初のフィールドの各文字列の合計を維持するために連想配列を使用します。このEND
ブロックは入力の終わりに実行され、計算された合計を文字列と共に出力します。
また、この解決策は、質問に示すように、最初のフィールドが空白文字を含まない単一の単語であると仮定します。
シェルループを使用してソースファイルからソートされた行を読み取り、新しい最初のフィールドが表示されるたびに2番目のフィールドの合計を印刷してリセットします。
unset -v prev
sort file |
{
while read -r key value; do
if [ "$key" != "${prev-$key}" ]; then
# prev is set and different from $key
printf '%s:%d\n' "$prev" "$sum"
sum=0
fi
prev=$key
sum=$(( sum + value ))
done
if [ "${prev+set}" = set ]; then
printf '%s:%d\n' "$prev" "$sum"
fi
}