行の抽出が簡単にできるgrepと、列の抽出に便利なawkを組み合わせると、コマンドライン上での操作で簡単に作業ができる場合も多いかと思います。
grepで指定した行に対して、awkで指定した列の総和を求める操作をワンライナーで書いてみたいと思います。
順を追って見ていきたいと思います。
スポンサーリンク
grepとawkをパイプでつなぎながら動作を確認していく
※awkの使い方をまとめて一覧にしました。
参考:awk入門-使い方まとめ一覧-
参考:awk入門-使い方まとめ一覧-
下記のようなin.txtがあったとします。
ここで、"2016"と"b"の文字列がある行に対して、3列目の総和を求めていきます。
$ cat in.txt 2015 a 55 2016 a 35 2016 a 35 2016 a 22 2016 b 88 2016 b 98 2016 b 45 2016 b 35 2017 c 31
パイプでつないでgrepでand検索
まずは下記のようにgrepで"2016"を含む行を抽出できたことを確認します。
$ grep "2016" in.txt 2016 a 35 2016 a 35 2016 a 22 2016 b 88 2016 b 98 2016 b 45 2016 b 35
そして、更に、パイプでつないでgrepで"b"の行を抽出して、and検索をかけます。
"2016"と"b"の両方を含む行を抽出できていることが確認できます。
$ grep "2016" in.txt | grep "b" 2016 b 88 2016 b 98 2016 b 45 2016 b 35
スポンサーリンク
更に、パイプでawkに渡して列の総和を求める
更に、パイプでつないでawkに渡してあげて、awkで3列目の総和を求めます。
3列目は変数$3になりますので、1行処理する毎に足し合わせていきます。
最後にENDブロックで総和を表示しています。
$ grep "2016" in.txt | grep "b" | awk '{sum += $3} END{print "sum=" sum}' sum=266
awkのワンライナーで行と列を指定して総和を求める
上記のような方法は、awkだけでももちろんワンライナーで書けてしまいます。
下記のように、メイン処理ブロックの条件部を追加して、$0(1行)の中に"2016"と"b"が両方含む場合に処理するようにしました。一応、マッチした行を表示して、最後に総和を出力しています。
$ awk '$0 ~ /2016/ && $0 ~/b/ {print $0;sum += $3} END{print "sum=" sum}' in.txt 2016 b 88 2016 b 98 2016 b 45 2016 b 35 sum=266
用途によってはawkだけでもいけますが、grepとawkを常に意識することで、より幅が広がると思っています。
わかりやすく簡単にが大事だと思いますので、いくつか選択肢を持っておいて、柔軟に使い分けていくのが良いかと思います。
スポンサーリンク