まだ sort して uniq してるの?

2 min read読了の目安(約1800字 2

この記事の要点

  1. awkを使えば『出てきた順にuniq』出来る
  2. 『X回重複したもの』も簡単に出せる
  3. しかも速い(らしい)

※この記事は以下書籍の内容を参考に書いています。
書籍:「シェル芸」に効く!AWK処方箋

intro

エンジニアであれば、ログ調査でセッション一覧を出力する時など
『多数ある要素から重複を排除する』シーンは多いかと思います。
私の身の回りではsortしてuniqしている人が多いように感じますが
awkのほうが便利で速いです。

awkとは

awk[1]はUNIXで開発されたプログラミング言語で、テキスト処理に長けています。
awkを使いこなせると、コマンドで出来ることがより"多く"なります(激寒)

awkの記法

awk '条件{命令}' 入力
awk sample
boomkun@zenn:~$ echo "test" | awk '$0=="test"{print "ok"}'
ok

何が起きているか分かりますでしょうか?
条件記述部$0=="test"が真であるため、命令部{print "ok"}が実行されたのです。
簡単な説明は以上として、今回覚えておきたいawkの前提知識が以下の3つです。

前提知識1

条件記述部が真(=1)の場合に実行する。

前提知識2

$0は行全体を指す

前提知識3

配列を使える

さっそくやってみましょう。

awkでの重複排除(基礎編)

以下のようなhoge.txtというファイルが仮にあったとします。

hoge.txt
A A A
C C C
B B B
A A A
A B C
B B B
C C C
C B A

出てくる要素としてはAAA,BBB,CCC,ABC,CBAの5つ。
コマンドを用いて求める場合、sort,uniqだと

boomkun@zenn:~$ cat hoge.txt | sort | uniq
A A A
A B C
B B B
C B A
C C C

sortuniqの代わりにawkを使うと

boomkun@zenn:~$ cat hoge.txt | awk '!a[$0]++{print}'
A A A
C C C
B B B
A B C
C B A

出てきた順にuniqされているのが分かるかと思います。

どういう理屈で重複が排除されているのか

条件記述部の!a[$0]++の部分について深堀りしてみましょう。
aという配列に$0をぶち込み、返ってきた値を後置インクリメントしています。
つまり、『1度目は真、2度目以降は偽』となるため
最初に出てきた時のみ{print}アクションがおこります。

awkでの重複排除(応用編)

今回紹介したawkの重複排除!a[$0]++は応用も幅広くききます。

  1. 重複しているもののみ出力
    !を外してa[$0]++とするだけです。
boomkun@zenn:~$ cat hoge.txt | awk 'a[$0]++{print}'
A A A
B B B
C C C
  1. $xの重複するものを出力
    配列に入れるものをa[$2]とすれば『$2の重複するものを出力』出来るでしょう。
  2. 重複行がX個以上あるものだけ出力
'a[$0]++ == X'

outro

うまく説明できた気がしませんが、awkについての小ネタでした。
たまに業務につながることがあるので、シェル芸の問題を解くのは息抜きにオススメです。
なにより時系列が大事なセッション抜き出しで、『sortせずuniq』出来るのは
ログ調査などで大きな助けになるかもしれませんね。

参考書籍:「シェル芸」に効く!AWK処方箋

脚注
  1. AWK - Wikipedia ↩︎