シェル芸について調べてた時にAWK使えたほうがいいよAWK!
ってな情報に出会ったんだけどAWKってなに?おーく?豚なの?
みたいなレベルからとりあえずどんなものか触ってみようと思ってまとめてみました。
AWKってなんやねん? in wikipedia
(1)名前の由来は開発者の名前から。
アルフレッド・エイホ、ピーター・ワインバーガー、ブライアン・カーニハンの三人のLastName取ってAWK。
モンスターとか樫の木じゃないのね。
(2)UNIX上で開発されたプログラミング言語
ぷ、プログラミング言語なの?ツールじゃないのか。
(3)改行でレコードが区切られ、各レコードのフィールドは空白類で区切られているようなテキストファイルを扱えるがカスタマイズも可能。
なるほど、文字列操作のための言語なのね。デフォでCSVファイルとかを操作したい時に使うと。
(4)文字列と数値を扱うプログラミングも可能である。
CUIでEXCEL関数とか使うイメージだろーか?
なんとなくわかった気分になったので一旦座学はおいといて手を動かすことにする。
まずは慣れるためにAWKプログラミングのさわりをいくつか。
こちらを参考にさせていただきました。
https://hydrocul.github.io/wiki/commands/awk.html
(1)とりあえずハローワールド。
awk 'BEGIN { print "Hello, AWK world!" }'
ほむほむ、ワンライナーで書く場合もBEGIN句で開始して中身を記述すると。
ちなみにBEGIN指定しないで以下のように記述すると、なんか延々ハローワールドが表示された。
どんな仕様だ?
awk '{ print "Hello, AWK world!" }'
(2)CSVファイルの中身を単純にプリントしてみる。
サンプルcsv
# awk.txt
1 2 3 4 5
a b c d e
P P A P
awk '{print $1 $2 $3 $4 $5}' awk.txt
>12345
>abcde
>PPAP
ちなみに変数?間の空白は詰めても問題なかった。
(3)四則演算してみる。
# 加算:
awk '{print $1 + $2}' awk.txt
>3
>0
>0
# 減算:
awk '{print $4 - $1}' awk.txt
>-1
>0
>0
# 乗算:
awk '{print $5 * $3}' awk.txt
>15
>0
>0
# 除算
awk '{print $4 / $2}' awk.txt
>2
awk: division by zero
input record number 2, file awk.txt
source line number 1
まずわかったのは文字列はゼロとして扱われること。
加減乗まではゼロが計算式に入ってもゼロが吐かれるだけで問題ないけど、
除算の場合ゼロディバイドになってエラーが出る。
(4)区切り文字へんこう。
サンプルCSV
# awkd.txt
1,2,3,4,5
a,b,c,d,e
P,P,A,P
awk -F, '{print $1 $2 $5 $1*$3}' awkd.txt
>1253
>abe0
>PP0
区切り文字はカンマでもパイプでもいけるっぽい。
ちなみにパイプの場合はエスケープがいるようだった。
awk -F\| '{print $1 $2 $5 $1*$3}' awkd.txt
(5)行番号を出力
awk '{print NR $1 $2 }' awk.txt
>112
>2ab
>3PP
# ゼロから始める
awk '{print NR-1 $1 $2 }' awk.txt
>012
>1ab
>2PP
美しくないけどとりあえず。
(6)検索
awk '/1/' awk.txt
# grepのこれと同じ。
grep 1 awk.txt
オフィシャルから使いそうなコマンドを拾ってくるテスト。
Linuxコマンドと合わせてワンライナーコマンド
(1)対象ファイルの各行のレコード長を表示
## こんなかんじのねろねろなサンプルテキストファイルを用意
aasdasffsanlfkas
asdlasfasdas
sadasdm
fas
sdlkvsfa
12321312rsdvmlsk
23dslks
# コマンド
awk '{print NR":"length($0)}' awk.txt
1:16
2:0
3:12
4:7
5:3
6:8
7:16
8:7
列番号が美しくなかったので : を挟んで見る。
(2)for loop
まずはぐるぐる。
cat awk.txt |
wc -l |
xargs -Iline awk '
{
for (i=1; i<line ; i++)
print $i
}
' awk.txt
手順的には、
(1)awk.txtの中身をcatで展開
(2)wcで行数を取得(直接ファイルから取得するとファイル名が含まれてしまうためパイプ渡し)
(3)変数lineに行数を引数として渡す。
(4)forloopで行数分のレコードをprintする。
(3)FizzBuzz
せっかくなのでFizzBuzzも書いてみる。
awk '
BEGIN {
for (i=1; i<100; i++)
if (i%3==0 && i%5==0)
print "FizzBuzz!"
else if (i%3==0)
print "Fizz!"
else if (i%5==0)
print "Buzz!"
else
print i
}
'
こうしてみると普通のプログラミング言語なんですねぇ。
ってことでまた何かあれば書きます。