次のファイルがあります。
A 100
A 200
A 300 #sum=600
B 400
B 500 #sum=900
A 600
A 700
A 800 #sum=2100
私は出力が次のようになります:
A 600
B 900
A 2100
C sum_of_C
D sum_of_D
for
、sed
およびを使用してgrep
これを行うことができますawk
。
ところで勉強中だから台本awk
を書きたいですawk
。これまで私は以下を持っています:
if (${NR {print $1}} == ${NR-1 {print $1}})
sum+=$2
print $0"\t"sum
else
sum=$2
print $0"\t"sum
awk -f awkscript file
成功しませんでした。解決策は何ですか?
ベストアンサー1
if
あなたがそこで何をしたいのかわかりません。目標の場合、フィールド数NR
に使用されるレコード数。これらの真ん中にブロックをNF
配置することはできません。{}
あなたの目標は、この行のフィールド値を前の行のフィールド値と比較し、新しいデータ「グループ」に達したときに合計を印刷することです。その場合、このスクリプトはあなたが望むことを行い、あなたの目標とほぼ同じだと思います。
{
if (last && $1 != last) {
print last, sum
sum = 0
}
sum = sum + $2
last = $1
}
END {
print last, sum
}
last
前の行の最初のフィールド()値を保持する新しい変数を作成します。$1
私たちはこれを見て、私たちが見ているグループを追跡するために使用します。
{ ... }
各行に対して(最上位レベルにあるため)最初にa)がlast
設定されているか(最初の行に何も印刷しないため)、b)最初のフィールドの値がlast
。そうであればlast
、値、空白、,
計算sum
された内容を印刷します。 (タブをご希望の場合は"\t"
先ほど引用符で囲んで使用してください)- 印刷後、
sum
ゼロにリセットされます。 $2
どちらにしても、2番目のフィールド()の値をに追加しますsum
。- 各行に最初のフィールド(グループ)を保存することで、
last
次の行の比較に使用できます。 - 最後に、最後のグループを印刷しようとしています。この目的のために、我々は
END { ... }
ブロックを使用します。データが不足すると、プログラムの終了時に実行されます。以前のように、合計で作業しているグループを印刷します。
私が実行した場合:
awk -f sum.awk < data
あなたのデータファイルを使用して、次のような結果を得る。
A 600
B 900
A 2100
予想通り。
awkでも別の方法でも、これを行うより簡単な方法があります。特に、上記の本文を次のように置き換えることができます。
last && $1 != last {
print last, sum
sum = 0
}
{
sum = sum + $2
last = $1
}
ここでは、明示的なテストの代わりにawkの条件付きブロック構文を使用しますif
。プログラムは上記と同じように動作しますが、より慣用的です。この例には大きな違いはありませんが、awkを学んでいるかどうかを知っておくと便利です。
#sum=
提供されたファイルの例が実際に行(または同様のもの)を持つファイルの例である場合は、次のスクリプトを使用できます。
{
sum = sum + $2
if (NF == 3) {
print $1, sum
sum = 0
}
}
各行に対して、2番目のフィールドの値をsum
変数に追加します。正確に3つのフィールド(NF == 3
)を含む行から合計を印刷し、sum
ゼロにリセットします。