Linuxコマンド - awk

提供:MochiuWiki : SUSE, EC, PCB
ナビゲーションに移動 検索に移動

概要

awkコマンドとは、入力として受け取った文字列に対して、フィールド区切り文字やレコード区切り文字を指定して、
列に対する処理を行うためのコマンドである。


awkのインストール

パッケージ管理システムからインストール

多くのLinuxディストリビューションでは、パッケージ管理システムからgawkをインストールすることができる。

sudo zypper install gawk


ソースコードからインストール

もし、別途インストールする必要がある場合、ソースコードからgawkをインストールする。

gawkのビルドに必要なライブラリをインストールする。

sudo zypper install mpfr-devel readline-devel gettext-runtime gettext-tools intltool libsigsegv-devel


GNUソフトウェアの公式Webサイトにアクセスして、ソースコードをダウンロードする。
ダウンロードしたファイルを解凍する。

tar xf gawk-<バージョン>.tar.xz
cd gawk-<バージョン>


gawkをビルドおよびインストールする。

mkdir build && cd build

../configure --prefix=<gawkのインストールディレクトリ>
make -j $(nproc)
make install


gawkの実行に必要な依存関係のライブラリをインストールする。

sudo zypper install libsigsegv2


~/.profileファイル等に、環境変数PATHを追記する。

vi ~/.profile


# ~/.profileファイル

export PATH="/<gawkのインストールディレクトリ>/bin:$PATH"
export LD_LIBRARY_PATH="/<gawkのインストールディレクトリ>/lib64:/<gawkのインストールディレクトリ>/lib:$LD_LIBRARY_PATH"



awkコマンドの基本書式

awkコマンドの基本書式を以下に記載する。

awk -F'[フィールド区切り文字(複数可能)]' -v '変数=xx' '{awkコマンド}' file



フィールドの出力

標準出力を行うawkコマンドのprintを使用して、awkコマンドで指定したフィールドを取得する。
-F'[フィールド区切り文字]'オプションを指定しない場合、区切り文字にはタブまたは半角スペースが選択される。

1フィールド目を出力 : print $1

# 実行
echo 1 2 3 4 | awk '{print $1}'

# 出力
1


2フィールド目の出力 : print $2

# 実行
echo 1 2 3 4 | awk '{print $2}'

# 出力
2


全ての文字列の出力 : print $0 または print

# 実行
echo 1 2 3 4 | awk '{print $0}'

# 出力
1 2 3 4


# 実行
echo 1 2 3 4 | awk '{print}'

# 出力
1 2 3 4


フィールド区切り文字の指定

フィールド区切り文字として、":"を指定する。

# 実行
echo 1:2:3:4 | awk -F'[:]' '{print $1}'

# 出力
1


また、フィールド区切り文字は複数指定できる。

以下の例では、フィールド区切り文字として、":"と"/"を指定している。
並べて記述することで、":"と"/"がフィールド区切り文字として扱われる。

# 実行
echo 1:2/3:4 | awk -F'[:/]' '{print $3}'

# 出力
3


複数フィールドの出力は、半角スペースで区切られる。(OFSを指定していないため)
OFSについては、後述のセクションを参照すること。

# 実行
echo 1:2/3:4 | awk -F'[:/]' '{print $1,$2}'

# 出力
1 2



OFS

OFS(Output Field Separator)とは、awkコマンドの組み込み変数であり、出力のフィールド区切り文字を指定する。
-vオプションは、変数(variable)を指定するという意味のオプションである。

-v '変数=xx'


以下の例では、OFSに半角スペースを指定して、フィールドの出力を#で区切る。

# 実行
echo 1:2/3:4 | awk -F'[:/]' -v 'OFS= ' '{print $1,$3}'

# 出力
1 3



RS

RS(Record Separator)とは、awkコマンドの組み込み変数であり、入力のレコード区切り文字を指定する。

以下の例では、/を区切り文字に指定して、1:2と3:4に分けている。
/をレコード区切り文字にして、各レコードから1フィールド目を取得している。
出力は、改行で区切って出力される。(ORSが指定されていないため)

# 実行
echo 1:2/3:4 | awk -F'[:]' -v 'RS=/' '{print $1}'

# 出力
1
3


# 実行
echo 1:2/3:4 | awk -F'[:]' -v 'RS=/' '{print $1,$2}'

# 出力
1 2
3 4


フィールド区切り文字とレコード区切り文字で同じ文字がある場合、レコード区切り文字が優先される。

# 実行
echo 1:2/3:4 | awk -F'[:/]' -v 'RS=/' '{print $1,$2}'

# 出力
1 2
3 4



ORS

ORS(Output Record Separator)とは、awkコマンドの組み込み変数であり、出力のレコード区切り文字を指定する。

以下の例では、"This is ORS"を指定して、レコードの出力を区切っている。

# 実行
echo 1:2/3:4 | awk -F'[:/]' -v 'RS=/' -v 'ORS=This is ORS' '{print $1,$2}'

# 出力
1 2This is ORS3 4



OFSとORSの明示

以下の例では、OFSは空白4つ、ORSは改行2つにしている。
また、\nは改行を示す。

# 実行
echo 1:2/3:4 | awk -F'[:/]' -v 'OFS=    ' -v 'RS=/' -v 'ORS=\n\n' '{print $1,$2}'

# 出力
1    2
3    4



最終フィールドの取得 : $NF

最終フィールドを取得するとして、$NFが用意されている。

# 実行
echo 1:2/3:4 | awk -F'[:/]' '{print $NF}'

# 出力
4


# 実行
echo 1:2/3:4 | awk -F'[:/]' '{print $NF-1}'

# 出力
3



printf

printの他に、printfも使用できる。

# 実行
echo 1:2/3:4 | awk -F'[:/]' '{printf "%s\n%s\n",$NF,$NF-1}'

# 出力
4
3



awkを使用したフィルタリング

空白で区切られた特定のフィールドを切り出す

awkの組み込み変数$xには、xフィールド目に存在する文字列が設定されている。
これを、awkprint文で出力することにより、特定のフィールドのみを切り出すことができる。

cutコマンドでも空白区切りのフィールドを切り出すことが可能だが、特に、フィールド間の空白数が一定でない場合はawkコマンドを使用する。
一定の空白数の有無に関わらず、空白区切りのフィールドを切り出すには、awkコマンドを使用した方がよい。

awk '{ print $フィールド番号 }'  # awkコマンドの組み込み変数で対象フィールドのみを出力する


以下の例では、特定のフィールドを切り出している。

cat test.txt

111    ABC         abc
           222 DEF   def
  333           GHI ghi
444   JKL               jkl
555  MNO   mno
    666 PQR pqr
777                STU  stu
                      888 VWX vwx
999 YZ yz


1フィールド目を切り出す。

awk '{ print $1 }' test.txt

111
222
333
444
555
666
777
888
999


2フィールド目を切り出す。

awk '{ print $2 }' test.txt

ABC
DEF
GHI
JKL
MNO
PQR
STU
VWX
YZ


3フィールド目を切り出す。

awk '{ print $3 }' awktest.txt

abc
def
ghi
jkl
mno
pqr
stu
vwx
yz


対象となる行を特定してフィールドを切り出す。

行番号を指定することで、処理対象となる範囲を限定することができる。
また、行番号指定の場合は、==以外にも、<><=>=!=が使用できる。
さらに、||(OR条件)や&&(AND条件)で複数の条件を指定することもできる。

NRは行番号を表すawkコマンドの組み込み変数である。

awk '(NR == 行番号){ print $フィールド番号 }'  # awkコマンドに処理対象とする行番号を指定する


1行目のみを処理対象とする。

awk '(NR == 1){ print $1 }' test.txt

111


1行目および9行目を処理対象とする。

awk '(NR == 1 || NR == 9){ print $1 }' test.txt

111
999


5行目を超えて8行目以下、つまり、6行目から8行目までの行を処理対象とする。

awk '(NR > 5 && NR <= 8){ print $1 }' test.txt

666
777
888


空白で区切られたフィールドの順番を入れ替える

"hoge fuga foo bar"のように空白で区切られた各フィールドを、"bar hoge bar foo"のように順番を入れ替えて出力するには、awkコマンドを使用する。

awkコマンドにおいて、$xはx番目のフィールドを意味する。
つまり、フィールドの順番を入れ替えるには、出力したい順番で$xを指定する。

例えば、3つのフィールドの順番を逆にする場合は、$3" "$2" "$1と指定する。
" "は、フィールド間のスペースを意味するため、これを指定せずに実行すると、各フィールドが結合した状態で出力されてしまう。

awk '{ print $フィールド番号" "$フィールド番号" "..." "$フィールド番号 }'  # awkコマンドで各フィールドの番号を出力したい順に指定する


cat shuffle.txt

111 ABC abc
222 DEF def
333 GHI ghi
444 JKL jkl
555 MNO mno


以下の例では、空白スペース" "を指定していないため、全て結合された状態で出力されている。

awk '{ print $3 $1 $2 }' shuffle.txt

abc111ABC
def222DEF
ghi333GHI
jkl444JKL
mno555MNO


以下の例では、$xの間に" "を指定しているため、フィールド間がスペースで区切られている。

awk '{ print $3" "$1" "$2 }' shuffle.txt

abc 111 ABC
def 222 DEF
ghi 333 GHI
jkl 444 JKL
mno 555 MNO


以下の例では、同じフィールドを2回出力している。

awk '{ print $3" "$1" "$1" "$2 }' shuffle.txt

abc 111 111 ABC
def 222 222 DEF
ghi 333 333 GHI
jkl 444 444 JKL
mno 555 555 MNO


シェルスクリプトに組み込んで使用する場合は、以下のように、パイプでデータを引き渡して実行することが多い。
以下の例でのように、処理対象データから予め不要な部分を取り除いた上でawkに引き渡すことで、awkを簡素に記述することができる。

head -n 3 shuffle.txt | awk '{ print $2 }'

ABC
DEF
GHI


※備考
awkはコマンドではなく、インタプリタでありシェルスクリプトとは異なるスクリプト言語である。
元々、テキスト処理のために開発されたスクリプト言語であるため、シェルスクリプトよりも高速にテキスト処理を行うことができる。

awkはシェルスクリプトに組み込むことが容易であるため、awkのみで使用するよりもシェルスクリプト内でフィルタとして使用されることが多い。
シェルスクリプトで行数の多いテキストファイルを処理する場合、一部にawkを使用することで高速なプログラムを記述することができる。

テキストファイルの処理にはPerl等を使用した方が便利な場合もあるが、Perl等が使用できない環境ではawkを使用する方がよい。