背景
テキストファイルからある列を抽出、加工したりする処理は基本Pythonを使って自動化してきたけど、Linuxサーバーをいじったりすることが多くなって、Linuxコマンドの出力結果について、ちゃちゃっと操作したいなって思うことが増えてきた。
調べたらAwkコマンドというのが便利らしいと知ったので、使ってみる。
Awkとは
テキスト処理ツールの一種で、行単位でテキストを処理するために使用されるスクリプト言語。行指向の処理が得意なため、UNIXやLinuxシステムで非常に便利。
パターンマッチングとアクションの組み合わせでテキストを抽出・加工・変換が可能。
使い方
awk [options] 'pettern {action}' 標準入力
※区切り文字を指定しない場合は、スペースが指定される。
組み込み変数
-
\$1, \$2, ..., \$n
第N列目のデータ(1始まり) -
NF
フィールド(列)の数(1始まり) -
NR
行番号(1始まり)
実際に使ってみる
基本的な使い方
ls
の結果をいじってみる。
$ ls -l
drwx------@ 70 test1 staff 2240 Apr 29 20:13 Desktop/
drwx------@ 17 test2 staff 544 Apr 29 21:12 Documents/
drwx------@ 142 test3 staff 4544 Apr 29 21:36 Downloads/
- まずは、所有者だけ抜き出してみる。(第2フィールド)
$ ls -l | awk '{print $3}'
test1
test2
test3
何も指定していないので、フィールドの区切り文字はスペース。
→csvファイルだったら、こんな感じls -l | awk -F "," '{print $3}'
- 次に、所有者が
test2
の時だけ、行ごと出力する。
$ ls -l | awk '$3 == "test2" {print}'
drwx------@ 17 test2 staff 544 Apr 29 21:12 Documents/
- ファイルサイズが2000以上の行を出力する。
$ ls -l | awk '$5 >= 2000 {print}'
drwx------@ 70 test1 staff 2240 Apr 29 20:13 Desktop/
drwx------@ 142 test3 staff 4544 Apr 29 21:36 Downloads/
- 奇数行目だけ出力
$ ls -l | awk 'NR%2!=0 {print}'
drwx------@ 70 test1 staff 2240 Apr 29 20:13 Desktop/
drwx------@ 142 test3 staff 4544 Apr 29 21:36 Downloads/
パターンで正規表現も使用できるようなので、使ってみる。
使い方:patternのところが→$n ~ "正規表現"
ls
の結果が下記だとする。
$ ls -l
drwx------@ 70 test1 staff 2240 Apr 29 20:13 Desktop/
drwx------@ 17 test2 staff 544 Apr 29 21:12 Documents/
drwx------@ 142 testtest3 staff 4544 Apr 29 21:36 Downloads/
- 所有者が
test + 数値
になってる場合のみ行を出力したい。
$ ls -l | awk '$3 ~ "^test[1-9]+" {print}'
drwx------@ 70 test1 staff 2240 Apr 29 20:13 Desktop/
drwx------@ 17 test2 staff 544 Apr 29 21:12 Documents/
→testtest3の行は表示されてない。
区切り文字の指定-F
オプション-F
を使うと、区切り文字の指定ができる。
例としてユーザ情報/etc/passwd
からユーザ名を取り出してみる。
※/etc/passwd
はユーザ情報が↓の形式で保存されている。
ユーザ名:パスワード:UID:GID:連絡先:ホームディレクトリ:ログインシェル
$ cat /etc/passwd # 中身はダミー
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
hoge:x:4:7:hoge hoge:/var/spool/lpd:/sbin/nologin
まず、-F
オプションを指定せずに実行
$ cat /etc/passwd | awk '{print $1}'
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
hoge:x:4:7:hoge
↑出力結果を見ると、区切り文字がデフォルトの空白になっているため、うまくいかない。
(一番下のhoge
の行に空白が含まれているので、中途半端なところで区切られている。)
なので、-F
で区切り文字を指定
$ cat /etc/passwd | awk -F':' '{print $1}'
root
bin
daemon
adm
lp
hoge
区切り文字を:
にしたのでうまくいった!
感想
かなり便利!
ばんばん使ってきたい。
awkは言語だから他にもいろいろできる。また、何かあったら他の使い方も調べてみよ。