Diary

Diary

日々学んだことをアウトプットする場として初めてみました

awk 入門

awk 入門

awk の使い方を簡単に紹介し、「awk 何それ?」っていう状態から「awk 使ったことあるよ」っていう状態になることを目指します。

awk

  • ファイルもしくは標準入力から渡された文字列を、パターン解析し処理していくような言語です。
  • ワンライナーで、パイプの一要素として使う方法」と「1ファイルに .awk ファイルとして記述する方法」があります
    • 今回はパイプで繋ぐ使い方の紹介が多めです。
  • 1行ごとに解析・行の中でも1フィールドごとにアクセスできる、といった使い方が基本となります。

オプション

よく使うオプションの一部を紹介します。

  • -F
    • フィールドの区切り文字を指定します
  • -v
    • 初期変数を定義します
  • -f
    • awk のコードをファイルから読み込ませたいときに使います

基本パターン

基本のパターンは、'pattern{ action }'となります。このことはぜひ頭に入れてください!

$ awk 'pattern{ action }'

各フィールドへのアクセス方法

field1 field2 field3 という行の入力があった場合、awk で用いるには$1, $2, $3と指定します。また、$0は行全体を表します

$ echo 1 2 3 4 5 | awk '{print $1}'
1
$ echo 1 2 3 4 5 | awk '{print $0}'
1 2 3 4 5

pattern の記述方法

pattern には条件を記述します。

普通の条件式のように、string == patternとしても良いですが、以下のように「~」を用いることで正規表現が使えます。

# どちらの書き方でも良い
"ABC" ~ "^[A-Z]+$"   # true
"ABC" ~ /^[A-Z]+$/   # true

# マッチしてないパターン(「!」で否定)
"012" !~ /^[A-Z]+$/   # true

特殊な pattern

2つの特殊な pattern として、BEGIN と END があります。その名の通り、BEGIN に続く{ action }は処理が始まる前に実行され、END に続く{ action }は処理が終わった後に実行されます。

BEGIN は初期変数や初期配列の定義、END は最終結果の出力などに使われることが多いです。

省略形

patternactionのどちらか一方は省略が可能です。

# 各フィールドには、$1, $2,...とアクセスします
$ echo hoge | awk '$1 == "hoge"{print "hoge found"}'
hoge found

# pattern が省略されると、全ての行に対して action が実行されます
$ echo -e 'hoge\nfuga' | awk '{print "hoge found"}'
hoge found
hoge found

# action が省略されると、行全てを出力します
$ echo hoge | awk '$1 == "hoge"'
hoge

変数

awk 組み込み変数

awk には、組み込みの変数がいくつか用意されています。

変数 説明
FILENAME input ファイルの名前
FNR ファイルの行数
FS フィールドの区切り文字(デフォルトは" ")
NF フィールドの数 (横)
NR レコードの数 (縦)
OFS 出力のフィールドの区切り文字
ORS 出力の行の区切り文字 (デフォルトは"\n")
RS 入力の行の区切り文字 (デフォルトは"\n")

環境変数

シェルの環境変数にもアクセスできます。ENVIRONという名前の配列に格納されています。

$ awk 'BEGIN{ print ENVIRON["HOME"]; print ENVIRON["USER"]}'
/Users/kokoichi
kokoichi

String メソッド

よく使う関数一覧

関数 説明
length(string) 文字列の長さを取得
substr(string, start, length) 部分文字列を取得
tolower(string) 小文字に変換
toupper(string) 大文字に変換
index(string, pattern) patten が含まれるか検索
split(string, array, regexp) 分割された文字列が array に格納される

使用例

$ echo "hogeHOGE" | awk '{print length($0)}'
8

# 1オリジンっぽい
$ echo "hogeHOGE" | awk '{print substr($1, 5, 4)}'
HOGE

$ echo "hogeHOGE" | awk '{print tolower($0)}'
hogehoge
$ echo "hogeHOGE" | awk '{print toupper($0)}'
HOGEHOGE

$ echo "hogeHOGE" | awk '{print index($1, "hoge")}'
1
# case に sensitive
$ echo "hogeHOGE" | awk '{print index($1, "hoGe")}'
0

# split の戻り値は配列の要素数
$ echo "hogeHOGE" | awk '{print "要素数: ",split($1, pi, /[oO]/)}END{for(i=1;i<=length(pi); i++){print pi[i]}}'
要素数: 3
h
geH
GE

Numeric メソッド

よく使う関数一覧

関数 説明
atan2(y, x) arctan(y/x) を -π ~ +π で返す
cos(x) cos関数
sin(x) sin関数
exp(x) exp関数
int(x) 整数値を返す
log(x) log関数
rand() 0<= x < 1 の一様乱数
srand(x) 乱数生成の seed を x にセットする
sqrt(x) √x

使用例

$ awk 'BEGIN{print rand()}'
0.924046
# 意図的に seed を変更しないと、ずっと同じ
$ awk 'BEGIN{print rand()}'
0.924046

# srand(x) を使って変更してみる
# x を指定しないと、現在時刻の秒が使われる
$ awk 'BEGIN{srand();for(i=0;i<5;i++){print rand()}}'
0.22799

おわりに

今回はあまり awk の実用例まで紹介できませんでした。

実際に、どのような場面で使えるのかをまた実演できたらと思います。