awkを10倍使いこなして働き方改革 | 瀬戸内の雲のように

awkを10倍使いこなして働き方改革

Posted: 2019-01-31


スポンサーリンク

目次

はじめに

近年の労働環境における大きなテーマである働き方改革。

まあ色々な捉え方・進め方があるわけですが、業務効率化という観点で言えばエンジニアに求められるものは大きいかと思います。

ということで今回は日常業務の効率化に効く(と思う)awkの使いこなし方を解説したいと思います。

まあ若干タイトル詐欺な感じも否めませんが、awkを10倍くらい使いこなして業務を効率化しましょう!ということで読んで頂ければ幸いです。

 

前提: awkとは

こちらの記事にわかりやすくまとめました。→ awkって何?何ができるの?をできる限りわかりやすく伝えたい をお読みください。

 

awkを10倍使いこなすために必要なこと

awkをより使いこなすためには以下3点を知る必要があります。

  • 省略形ではない、正式な文法
  • BEGIN句、END句の使い方
  • 判定条件の書き方

今回はこの3点にフォーカスして説明していきます。

  

1. 正式な文法とは

awkの経験値が浅い方は、awkの文法は

awk '{ print カラム番号 }' ファイル名

だと思っている方が多いのではないでしょうか。

 
これも間違いではないのですが、実際にはもっと色々指定できて、

awk 'BEGIN{ 前処理 }判定条件{ メイン処理 }END{ 後処理 }' ファイル名

のように書くことができます。
(このうち、いくつかを省略して書くことができ、省略すると最初の例のような文法になります)

 

実際の例

百聞は一見にしかず、実際に実行してみましょう。
こう言うファイルがあったとして、

$ cat file.txt
本文だよ

 
以下のようにコマンドを実行すると

awk 'BEGIN{print "前処理"}{print $0}END{print "後処理"}' file.txt

 
こういった結果になります。

前処理
本文だよ
後処理

 

詳細説明

これだけを見てもよくわからないと思うので、詳しく説明していきます。
先程の文法をわかりやすく書き直すと、以下のようになります。

picture

色で分けているのが処理の区切りになっています。
私が思うに、 awkの分かり辛いところは、このブロックを区切る文字が無いところ だと思います。
(他の言語であれば、 ; とか , とか入りそうなところ)

さて、先程少し書きましたが、この文法のうち、

  • BEGIN{前処理}
  • 判定条件
  • 後処理

は省略することができます。それらを省略すると

 
awk '{メイン処理}' ファイル名

となり、普段見慣れた文法になるはずです。

 

2.BEGIN句、END句の使い方

awkは基本的にファイル or 標準入力から行を読み込み処理を行いますが、入力を読み込む前後(1行目を読み込む前、最終行を読み込んだ後)にも処理を入れることができます。

それが、BEGINEND の2つの句です。

これを使うことで、例えば ファイル中のある数値カウントし、合計値・平均値を算出する といった用途でとても役に立ちます。

使用例: 数値のカウント

以下のようなファイルがあったとします。

$ cat score.txt
----------------
team1, Taro, 98
team2, Hanako, 73
team1, Ichiro, 87
team2, Shinichi, 76
team1, Ken, 85
team2, Dai, 69
----------------

このファイルから team1のメンバーの合計点・平均点を算出 してみます。

 
コマンド

$ grep "team1" score.txt | awk 'BEGIN{sum=0;count=0}{sum+=$3;count++}END{print "合計点: " sum " 平均点: " sum/count}'

結果

合計点: 270 平均点: 90

 
いかがでしょうか。少しわかりづらいかもしれませんので以下解説していきます。

解説

まず前提として最初の grepコマンド により、awkに渡される入力は以下になります。

team1, Taro, 98
team1, Ichiro, 87
team1, Ken, 85

 
これを受け取ったawkは以下の処理を行います。

  1. 変数sum, countにそれぞれ 0 を代入する
  2. 1行目を読み込み、変数sum+3カラム目(98)の数値計算を行い、変数countに +1 する
  3. 2行目を読み込み、変数sum+3カラム目(87)の数値計算を行い、変数countに +1 する
  4. 3行目を読み込み、変数sum+3カラム目(85)の数値計算を行い、変数countに +1 する
  5. printで sumの数値と sum/countの数値計算の結果を表示する

 
青字の部分が BEGIN句 で指定した部分、 赤字各行に対して実行されるメイン処理緑字END句 で指定した処理となります。

このように、 BEGIN入力を読み込む前の処理END全ての行を読み込んだ後に実行する処理 を定義できます。

 

3. 判定条件の書き方

3つ目は判定条件の書き方です。これもなかなか分かりづらいので丁寧に説明します。

まず先程の例をもう一度見てみると、最初に grepコマンドteam1の行を抜き出している ことが分かります。

$ grep "team1" score.txt | awk 'BEGIN{sum=0;count=0}{sum+=$3;count++}END{print "合計点: " sum " 平均点: " sum/count}'

実はこの部分をawkだけで書くことができます。その際に使うのが判定条件文です。

 
ということで、先程の例をawkだけに書き換えてみます。

$ awk 'BEGIN{sum=0;count=0}$1=="team1,"{sum+=$3;count++}END{print "合計点: " sum " 平均点: " sum/count}' score.txt

 
変わった点はBEGIN句の直後に $1=="team1," という文が入っている点です。

この文は、 $1が "team1," に一致した場合のみ、メイン処理を実行する という意味です。
この文を入れることにより、grepのように 一致する行だけを抜きだす ということが可能になります。

 
ちなみに、この条件分岐を使えば、 最初の行以外に処理を行う ということも容易に実現できます。

$ awk 'NR>1{ print }' score.txt
team2, Hanako, 73
team1, Ichiro, 87
team2, Shinichi, 76
team1, Ken, 85
team2, Dai, 69

NR というのは 読み込んだ行の番号(1からインクリメントされていく)ですので、 NR>1 という書き方で 2行目以降 という意味になります。

 

まとめ

今回記載した内容は他のコマンドで代替できることが多いのは事実ですが、他のコマンドとパイプで多段につなぐよりも入力の走査回数が少なくなるため高速に動作するはずです。
これは数ギガバイトというファイルに処理をする時には明確な差になります。

ということで、awkをより使いこなすためのコツを書きました。
お役に立てれば幸いです。


スポンサーリンク




コメント一覧


コメントを投稿する


お名前


コメント内容





TOP back