本連載は、Linuxのコマンドについて、基本書式からオプション、具体的な実行例までを紹介していきます。今回は、テキストのパターン処理を行う「awk(gawk)」コマンドです。
本連載では、Linuxの基本的なコマンドについて、基本的な書式からオプション、具体的な実行例までを分かりやすく紹介していきます。今回は、テキストのパターン処理を行う「awk(gawk)」コマンドです。連載第115回、第116回、第117回に続き、awkの基本的な使い方を説明します。
「awk」は空白などで区切られたテキストを処理するコマンドです。演算機能もあり、プログラミング言語としても使用されています。
Linux環境で使用されているのは、GNUプロジェクトによる「gawk」コマンドが多く、例えばCentOS 7の場合、awkは/usr/bin/gawkへのシンボリックリンクとなっています。
Ubuntu 15では、Michael D. Brennan氏による「mawk」が収録されています(awkは/etc/alternatives/awkへの、/etc/alternatives/awkは/usr/bin/mawkへのシンボリックリンク)。
どちらも、もともとのawkに加えてPOSIX 1003.2への準拠や組み込み変数、正規表現指定のバリエーションなどが拡張されています。
awk [オプション] [コマンド] [ファイル……]
※[ ]は省略可能な引数を示しています
短いオプション | 意味 |
---|---|
-f ファイル名 | awkスクリプトが書かれたファイルを指定する |
-F 区切り文字 | 区切り文字を指定する(デフォルトは空白文字) |
-v 変数名=値 | 変数を定義する |
※gawk(GNU版awk)の場合、長いオプションも使用可能。-fは--file program-file、-Fは--field-separator、-vは--assign。gawkにはこの他にも多数のオプションがある。
変数名 | 意味 |
---|---|
ARGC | 引数の個数 |
ARGV | 引数(配列) |
ENVIRON | 環境変数を収めた連想配列。例えば環境変数LANGならばENVIRON["LANG"]と参照できる |
FILENAME | 現在処理しているファイルの名前 |
FNR | 現在処理しているファイルのレコード番号(処理しているファイルが1つの場合はNRと同じ値になる) |
FS | フィールドの区切り文字(-Fオプションで変更可能、デフォルトはスペース) |
NR | 現在処理しているレコード番号(行番号) |
OFS | 出力時のフィールドの区切り(デフォルトは空白) |
ORS | 出力時のレコードの区切り(デフォルトは改行) |
RS | レコードの区切り(デフォルトは改行) |
awkコマンドでは「パターン {アクション}」として処理内容を指定します。パターンに合致したらアクションを実行する、という意味です。例えば「ls -l | awk '/^l/ { print }'」であれば、「ls -lで、lから始まっている行(シンボリックリンク)を出力する」となります(連載第116回)。
ここで、アクションが「print」のみの場合、1行全体を出力します。特定のフィールド、例えば9番目(ファイル名)のフィールドだけを出力したい場合は、「print $9」のように指定します(画面1)。
ls -l | awk '/^l/ { print }'
ls -l | awk '/^l/ { print $9 }'(画面1)
画面1では「ls -l /」でルートディレクトリを対象として、awkでシンボリックリンクだけを選んで出力しています。コマンド例では読みやすくするために記号の前後に空白を入れていますが、この空白は省略可能です。
1つ目のコマンド例はアクションがprintのみなので、アクション全体を省略しています。
シンボリックリンクの場合、「ls -l」では、9番目にファイル名、10番目に「->」という記号、11番目にリンク先が出力されます。
9番目のフィールドは「$9」と表すことができるので、9〜11番目のフィールドを出力するには、「print $9,$10,$11」または「print $9 $10 $11」のように書くことができます(画面2)。
ls -l / | awk '/^l/ { print $9,$10,$11 }'(画面2)
ls -l / | awk '/^l/ { print $9 $10 $11 }'
画面2の上の例のように「,」で区切った場合、「$9、区切り文字、$10、区切り文字、$11」という出力になります。デフォルトの区切り文字は空白なので「ファイル名 -> リンク先」という出力になります。
「print $9 $10 $11」の場合、$9と$10と$11が続けて出力されるので「ファイル名->リンク先」となります。
awkの組み込み変数「OFS」で出力時の区切り文字を変更すると、この違いがより分かりやすくなります。OFSは出力処理の前に変更したいので、BEGIN(連載第117回)を使用しています(画面3)。
ls -l / | awk 'BEGIN { OFS="*" } /^l/ { print $9,$10,$11 }'(画面3)
ls -l / | awk 'BEGIN { OFS="*" } /^l/ { print $9 $10 $11 }'
数字の桁数などの書式を指定したい場合には、printではなく「printf」を使用します。
基本的な指定の仕方は「printf "書式\n", 値」です。値と書式がセットとなり、書式の最後にある「\n」で改行します。毎回自動で改行されるprintとは違い、printfの場合は指定しないかぎり改行されない点に注意してください。
複数の値を出力したい場合は「printf "書式1 書式2 書式3\n", 値1, 値2, 値3」のように書きます。書式指定は幾つあっても構いませんが、必ず書式と値がペアになるようにします。
例えば「ls -l /usr/bin/」の結果のうち、5番目のフィールド(ファイルサイズ)が1000000を超える行について、「ファイル名($9)を40桁の左ぞろえ」で表示、同じ行に「ファイルサイズ($5)を1024で割り、数値部分は8桁で、うち小数点部分は1桁とする、末尾にKBを付ける」と指定すると画面4のようになります。
まずは実際のコマンド例と実行結果を見てみましょう。
ls -l /usr/bin/ | awk '$5 > 1000000 { printf "%-40s %8.1fKB\n", $9, $5/1024 }'(画面4)
書式設定の「"%-40s %8.1fKB\n"」の意味は以下の通りです。
最初の「%-40s」が、文字列(%s)の指定です。「-40」は“40桁で左ぞろえ”という意味です。
次の「%8.1f」が、数値(%f)の指定です。「8.1」で、全体は8桁の右ぞろえ、うち小数点以下の桁数は1桁、と指定しています。
その後ろの「KB\n」は、KBという文字列と改行です。printf全体では「printf "書式設定", $9, $5/1024」となっています。
従って、書式設定の「%-40s」部分には「$9」、つまりファイル名部分が出力されます。「%8.1f」部分には「$5/1024」、つまりファイルサイズを1024で割った値が出力されます。
printfでは次のように、さまざまな書式制御文字を使用できます。
書式制御文字 | 意味 |
---|---|
%d | 十進整数、%iも使用可 |
%e | 指数形式、%Eの場合Eが大文字で出力される |
%f | 小数点を使用した形式、桁数は「%4.3f」のように指定する |
%g | %fか%eで短くなる方、%Gの場合%E同様Eを大文字で出力 |
%o | 符合なしの八進数 |
%x | 符合なしの十六進数、%Xの場合アルファベットを大文字時で出力 |
%c | ASCIIキャラクタ、例えば「65」をいう数値を「A」と出力 |
%s | 文字列 |
※それぞれ「%3d」のように出力する桁数を指定できる。左ぞろえの場合は「-」記号を付けて「%-3d」のように指定(本文参照)。
※書式設定の中で%という文字を使いたい場合は「%%」のように書く。
このうちよく使うのは「%d」と「%f」です。それぞれ、整数と小数の書式を指定します。3桁の整数(右ぞろえ)であれば「%3d」、3桁未満の場合にゼロで埋めたい場合は「%03d」のように書きます。
echoでawkに数値を与え、試してみましょう(画面5)。
echo 数値 | awk 'printf "$3d\n" $0'(画面5)
(数値を3桁の右ぞろえで出力)
echo 数値 | awk 'printf "$03d\n" $0'
(数値を3桁でゼロを埋めて出力)
小数点以下の数値を出力したい場合は「%f」を使用し、「全体の桁数.小数点以下の桁数」と指定します(画面6)。
echo 数値 | awk 'printf "$8.1f\n" $0'(画面6)
(数値全体を8桁の右ぞろえ、小数点以下は1桁で出力)
数値を3桁区切りにして出力したい場合、どうすればよいのでしょうか。いったん数値を文字列に変換して、3桁ごとに「,」を出力するような処理を行います。
GNU版のawkの場合は「%'8.1f」のように「'」を入れることで3桁区切りの数値を出力できます(実際の出力内容はlocaleに従います)*)。
コマンドラインで実行する場合は、awkで行う処理全体を'〜'で囲んでいるため、書式設定の「'」を「\047」と書く必要があります(画面7)。処理を別のファイルに書き、「-f」オプションで読み込む方が分かりやすくなるでしょう。
※Ubuntu 15などで採用されているmawkでは、実行できない。
ls -l /usr/bin/ | awk '$5>1000000{printf "%-40s %\0478.1fKB\n",$9,$5/1024}'
西村 めぐみ(にしむら めぐみ)
PC-9801NからのDOSユーザー。PC-486DX時代にDOS版UNIX-like toolsを経てLinuxへ。1992年より生産管理のパッケージソフトウェアの開発およびサポート業務を担当。著書に『図解でわかるLinux』『らぶらぶLinuxシリーズ』『はじめてでもわかるSQLとデータ設計』『シェルの基本テクニック』など。2011年より、地方自治体の在宅就業支援事業にてPC基礎およびMicrosoft Office関連の教材作成およびeラーニング指導を担当。
Copyright © ITmedia, Inc. All Rights Reserved.