awk からの各行の出力に対して加算を実行するにはどうすればよいでしょうか?
例えば
cat foo | awk '{print $1}
42
42
42
42+42+42 (126) の答えを探しています。
私はこれを実行するためにforループを書こうとしているが、もっと簡単な方法があるはずだ
#Not Working, and way too complex
cat foo |awk '{ print $1 }'|for i in $1 do; foo=$(( foo+$(i) )) done| echo $foo
パイプすることはできますwc -l
が、行数のみが出力され、行は評価されません。
awk から各行を評価するにはどうすればよいでしょうか?
答え1
あなたの例を使用した基本的なアプローチ:
awk '{sum+=$1} END {print sum}' file
答え2
awk プログラムを制御できる場合は、@jasonwryan が示すように awk 内で加算を実行します。
awk が吐き出す数値を実際に合計したい場合は、出力を次のいずれかにパイプします。
| { tr '\n' '+' ; echo 0; } | bc
| { while read line; do ((sum+=line)); done; echo $sum; }
2 番目の例では、bash がパイプラインをサブシェルで実行するため、 echo コマンドはグループ化中括弧内にあります。そのため、サブシェルが終了したときに $sum 変数への変更は存在しません。
答え3
Bashは小数を扱うことはできませんが、整数の簡単な操作はできます。次のようなトリックを使うだけで済みます。プロセス置換変数をループ外からアクセスできるようにするには:
n=0;while read i; do let n+=$i; done < <(awk '{print $1}' foo); echo $n;
または
n=0;while read i; do n=$((n+i)); done < <(awk '{print $1}' foo); echo $n;
は、常に 0 であるn=0
ことを確認するためだけに存在します$n
。そうしないと、これらのコマンドを 2 回目に実行すると、126 ではなく 252 が返されます。
最も簡単な方法は、を使用しgawk
て計算を行うことですが、Perl ワンライナーを使用することもできます。
awk '{print $1}' foo | perl -lne '$k+=$_;END{print "$k"};'
フラグ-l
は改行 ( chomp
) を削除し、印刷される各文字列の末尾に 1 つ追加します。 は、-n
ファイルを 1 行ずつ読み取り、各行を として保存し$_
、 で提供されるスクリプトを実行することを意味します-e
。
または、すべてを Perl で実行します。
perl -alne '$k+=$F[0];END{print "$k"};' foo
Perl のフラグ-a
は、自動行分割をオンにします ( などgawk
)。デフォルトでは、フィールドはスペースで分割されますが、 を使用して変更できます-F
。結果のフィールドは配列として保存される@F
ため、最初のフィールドは になります$F[0]
。
答え4
このような単純な合計を計算するために私が通常使用するワンライナー方式は、xargs にパイプして awk からの出力をすべて 1 行にまとめ、次に sed を介してスペースをプラスに変換し、最後に bc に渡して計算を実行するというものです。
cat foo | awk '{print $1} | xargs | sed -e 's/ /+/g' | bc