Hello world を表示するプログラムは次のようになります。拡張子は特に決まりはありません。
{ print "Hello world!" }
AWK は grep や sed のようなフィルタコマンドとして実装されているため、何らかの入力が必要です。下記の様に実行します。
$ echo | awk -f hello.awk
下記のように、コマンドラインにプログラムを直接指定する方式もよく利用されます。
$ echo | awk '{ print "Hello world!" }'
簡単な利用例をいくつか紹介します。ちょっとした便利ツールとして重宝できそうってことがわかるかと思います。
# ls -l の結果から所有者とグループとファイル名だけを表示する $ ls -l | awk '{ print $3, $4, $9 }' yamada yamada hello.awk yamada yamada sample.awk # ファイル名がhello.awkのものだけ表示する $ ls -l | awk '$9=="hello.awk" { print $3, $4, $9 }' yamada yamada hello.awk # /etc/passwdを:をデリミタとしてユーザ名とホームディレクトリのみを表示する $ cat /etc/passwd | awk -F: '{ print $1, $6 }' root /root bin /bin # /etc/passwdのユーザ名とホームディレクトリを整形して表示する cat /etc/passwd | awk -F: '{ printf("%-8s %s\n", $1, $6) }' root /root bin /bin # df実行結果から2行目以降の第2カラムの合計を表示する $ df | awk 'NR>=2 {z+=$2}; END {print z}' 31097704
プログラムはコマンドラインに直接指定するか、-f でプログラムファイル名を指定します。入力ファイルは標準入力、または引数としてファイル名を渡します。
$ cat data.txt | awk '{ print $1, $2 }' # プログラムを直接指定 $ cat data.txt | awk -f sample.awk # プログラムファイルで指定 $ awk -f sample.awk data1.txt data2.txt # 入力データを引数で指定
プログラムファイルの先頭を #!/usr/bin/awk -f とすることで、プログラムファイルをコマンドとして直接実行することができます。
#!/usr/bin/awk -f { print $1, $8 }
$ chmod 755 sample.awk $ ps -ef | ./sample.awk
入力データはレコードとフィールドに分割されます。レコードは行、フィールドは空白文字で区切られたカラムに相当します。レコードとフィールドの区切り文字は ビルトイン変数 RS と FS で変更することができます。
field1 field2 field3 # record1 field1 field2 field3 # record2 field1 field2 field3 # record3
レコード全体は $0、フィールドは $1, $2, $3, ... で参照することができます。
{ print $0 } # レコード全体を表示 { print $1, $2, $3 } # 第1、第2、第3フィールドを表示
基本的な構文は下記の様になります。標準入力、または、引数で指定されたファイルを読み込み、パターンにマッチした行に対してアクションを実行します。
pattern1 { action1 } # pattern1にマッチしたらaction1を実行 pattern2 { action2 } # pattern2にマッチしたらaction2を実行 :
pattern を省略するとすべての行に対して action を行います。
{ action } # すべての行に対してactionを実行
{ action } を省略すると、{ print $0 } (その行を表示する)をアクションとして実行します。
/ABC/ # /ABC/ { print $0 } と同じ
パターンには /.../ で正規表現を記述できます。
/ABC/ { ... } # レコードの中にABCという文字列が含まれていればマッチ
if (...) 文の ... に記述するような条件式を記述することもできます。
$1 == "ABC" { ... } # 第1フィールドがABCであればマッチ
条件式で正規表現を使用することもできます。~ は正規表現にマッチしたらという演算子です。
$1 ~ /^#/ { ... } # 第1フィールド先頭が#で始まっていたらマッチ
条件1, 条件2 を記述した場合、条件1が真になる行から、条件2が真になる行までマッチします。
$1=="START", $1=="END" { ... } # 第1フィールドがSTARTである行から、ENDである行までマッチ
BEGIN, END はプログラムの一番最初と一番最後にアクションを実行します。
BEGIN { ... } # 最初に1度だけアクションを実行 END { ... } # 最後に1度だけアクションを実行
BEGINFILE, ENDFILE は各入力ファイルの開始時と終了時にアクションを実行します。
BEGINFILE { ... } # 最初に1度だけアクションを実行 ENDFILE { ... } # 最後に1度だけアクションを実行
アクションには、print で値を出力したり、if, while などで制御したりなど、通常のスクリプト言語と同様の処理を記述することができます。
{ if ($1 == "D") { # 第1フィールドの値が"D"であれば print $2, $3 # 第2、第3フィールドの値を出力する } }
セミコロン(;)を使用すると、1行に複数の文を記述することができます。
{ a = 1; b = 2; c = 3; print a, b, c }
# から行末まではコメントです。
# Comment... { print "Hello " # Comment... print "world!" # Comment... }
下記の演算子を使用できます。
(...) # グルーピング $num # 第nフィールドの値 +num # プラス(正数) -num # マイナス(負数) expr1 + expr2 # 加算 expr1 - expr2 # 減算 expr1 * expr2 # 乗算 expr1 / expr2 # 除算 expr1 % expr2 # 剰余 expr1 ^ expr2 # expr1のexpr2乗 expr1 ** expr2 # expr1のexpr2乗 expr++ # exprをインクリメント(インクリメント前の値が式の値) ++expr # exprをインクリメント(インクリメント後の値が式の値) expr-- # exprをデクリメント(デクリメント前の値が式の値) --expr # exprをデクリメント(デクリメント後の値が式の値) expr1 == expr2 # expr1がexpr2と等しければ expr1 != expr2 # expr1がexpr2と等しくなければ expr1 < expr2 # expr1がexpr2より小さければ expr1 <= expr2 # expr1がexpr2以下であれば expr1 > expr2 # expr1がexpr2より大きければ expr1 >= expr2 # expr1がexpr2以上であれば str ~ reg # 文字列strが正規表現regにマッチすれば str !~ reg # 文字列strが正規表現regにマッチしなければ !bool # boolが真でなければ(NOT) bool1 && bool2 # bool1かつbool2が真であれば(AND) bool1 || bool2 # bool1またはbool2が真であれば(OR) var = expr # varにexprを代入 var += expr # var = var + exprと同じ var -= expr # var = var - exprと同じ var *= expr # var = var * exprと同じ var /= expr # var = var / exprと同じ var %= expr # var = var % exprと同じ var ^= expr # var = var ^ exprと同じ var **= expr # var = var ** exprと同じ cond ? expr1 : expr2 # condが真であればexpr1、さもなくばexpr2
変数名[添え字] で配列を扱うことができます。
foo[1] = 123 foo[2] = "ABC" print foo[1] # => 123 print foo[2] # => ABC
添え字には文字列を使用することもできます。
foo["name"] = "Yamada" foo["age"] = 26 print foo["name"] # => Yamada print foo["age"] # => 26
配列の個数は length() で求めることができます。数値を添え字とする配列は次のようにしてループを回します。
foo[0] = "ABC" foo[1] = "DEF" for (i = 0; i < length(foo); i++) { print foo[i] }
添え字が文字列の場合は次のようにしてループを回します。
foo["name"] = "Yamada"
foo["age"] = 26
for (x in foo) {
print x "=" foo[x] # => name=Yamada, age=26
}
配列の中に該当の要素があるか否かを調べるには下記の様にします。
foo["name"] = "Yamada" if ("name" in foo) { print "Exist" }
配列要素を削除するには delete を用います。
foo["name"] = "Yamada" foo["age"] = 26 delete foo["name"] # foo["name"]を削除 delete foo # 配列foo自体を削除
次のようにして多次元配列を扱うことができます。
foo[1, 1] = 1001 foo[1, 2] = 1002 foo[2, 1] = 2001 foo[2, 2] = 2002 for (i = 1; i <= 2; i++) { for (j = 1; j <= 2; j++) { print foo[i, j] } }
多次元配列のように見えますが、内部的には添え字を SUBSEP("\034") で連結した1次元配列として扱っています。
foo["A", "B"] = "XYZ" print foo["A" SUBSEP "B"] # => XYZ print foo["A\034B"] # => XYZ
下記は、配列の配列を使用する例です。
foo[1][1] = 1001 foo[1][2] = 1002 foo[2][1] = 2001 foo[2][2] = 2002 for (i in foo) { for (j in foo[i]) { print foo[i][j] } }
print は変数や値を出力します。
print $1, $2, $3
値をカンマ(,)で連結するとビルトイン変数 OFS に指定された出力フィールドセパレータ(デフォルトは半角空白文字)で区切って出力します。
a = "AA"; b = "BB"; c = "CC";
print a, b, c # => AA BB CC
OFS を変更することで区切り文字を変更することができます。
a = "AA"; b = "BB"; c = "CC";
OFS = ","
print a, b, c # => AA,BB,CC
値をカンマ(,)で区切らない場合は文字列の連結が行われた後に出力されます。
a = "AA"; b = "BB"; c = "CC";
print a b c # => AABBCC
printf は、値をフォーマットして出力します。
printf "%d\n", 123 # 整数値を出力 printf "%f\n", 3.14 # 実数値を出力 printf "%s\n", "ABC" # 文字列を出力
%d などは引数の型を示します。下記のものを使用できます。
printf "d: %d\n", 123 # => 123 (10進整数) printf "i: %i\n", 123 # => 123 (10進整数) printf "u: %u\n", 123 # => 123 (符号無し10進整数) printf "x: %x\n", 123 # => 7b (16進整数) printf "X: %X\n", 123 # => 7B (16進整数) printf "o: %o\n", 123 # => 173 (8進整数) printf "f: %f\n", 123.45 # => 123.450000 (小数表記) printf "F: %F\n", 123.45 # => 123.450000 (小数表記) printf "e: %e\n", 123.45 # => 1.234500e+02 printf "E: %E\n", 123.45 # => 1.234500E+02 printf "g: %g\n", 1.2345e10 # => 1.2345e+10 (%f表記と%g表記を自動判断) printf "G: %G\n", 1.2345e10 # => 1.2345E+10 (%f表記と%g表記を自動判断) printf "c: %c\n", 0x41 # => A (ASCIIコード) printf "s: %s\n", "ABC" # => ABC (文字列) printf "%%: %%\n" # => % (%を文字として出力)
下記の様に桁数を指定して出力することができます。
printf "|%7d|\n", 123 # | 123| ... 7桁 printf "|%+7d|\n", 123 # | +123| ... 正の場合に+を表示 printf "|%-7d|\n", 123 # |123 | ... 左寄せ7桁 printf "|%07d|\n", 123 # |0000123| ... 0埋め7桁 printf "|%.2f|\n", 3.1416 # |3.14| ... 小数部2桁 printf "|%7.2f|\n", 3.1416 # | 3.14| ... 7桁(小数部2桁) printf "|%7s|\n", "ABC" # | ABC| ... 右寄せ7桁 printf "|%-7s|\n", "ABC" # |ABC | ... 左寄せ7桁
print や printf の出力を標準出力ではなくファイルに書き込むことができます。
print "ABC" > "data.txt" # ファイルdata.txtに新規書き込み print "ABC" >> "data.txt" # ファイルdata.txtに追記書き込み
print や printf の出力をコマンドにパイプ(|)で渡すこともできます。下記の例では ps -axu の結果を受け取り、VSZ($5) と COMMAND($11) の値をソートして表示します。
$ ps -axu | awk '{ print $5, $11 | "sort -n" }'
getline [var] getline [var] < file command | getline [var] command |& getline [var]
getline は標準入力やファイルからデータを読み取ります。下記では標準入力から変数 x にデータを読み取り、printf で出力しています。
BEGIN { printf "Input: " getline x printf "[%s]\n", x }
変数を省略すると、$0, $1, $2, ... に読み取ります。
getline printf "[%s] [%s] [%s] [%s]\n", $0, $1, $2, $3
下記の様にしてファイルからデータを読み取ることもできます。
BEGIN { while ((getline < "xx.dat") > 0) { printf "[%s] [%s] [%s] [%s]\n", $0, $1, $2, $3 } }
下記の様に | を用いることで、外部コマンドの実行結果からデータを読み取ることもできます。
BEGIN { cmd = "ps -ef" while (cmd | getline) { printf "[%s] [%s] [%s] [%s]\n", $1, $2, $3, $8 } }
|& を用いると外部コマンドにデータを渡し、その実行結果を読み出すことが可能となります。(双方向接続)
BEGIN { cmd = "base64" print "AAA" |& cmd close(cmd, "to") while ((cmd |& getline) > 0) { printf "[%s]\n", $0 } close(cmd) }
if文は、もし、... であればという条件を記述します。
if (n == 3) { # もしnが3と等しければ print "OK" # OKを表示 }
else は、さもなくば、を意味します。
if (n == 3) { # もしnが3と等しければ print "OK" # OKを表示 } else { # さもなくば print "NG" # NGを表示 }
アクションが1文であれば { や } は省略することができます。正確に言うと、if はひとつの文しか実行しないので、複数の文を実行するには { ... } で囲って複文にします。これは、while や do-while 文でも同様です。
if (n == 3) print "OK" else print "NG"
while文は、条件が成り立っている間、アクションを繰り返して実行します。
n = 0 while (n < 10) { # nが10より小さい間 print n # nを表示して n++ # nをインクリメントする }
do-while文も、条件が成り立っている間、アクションを繰り返して実行します。while文が、条件をチェックしてからアクションを実行するのに対して、do-while文はアクションを実行してから条件をチェックするため、最初から条件が成り立っていなくても最低1回はアクションが実行される点が異なります。
n = 0 do { print n n++ } while (n < 10)
for文は、n回処理を繰り返すといった場合に使用します。下記の例は10回繰り返し実行する例です。まず、i = 0 の初期化を行い、print n のアクションを実行し、i++ で i をインクリメントし、これを i < 10 の条件が成り立つ間繰り返します。
for (i = 0; i < 10; i++) { # iが0~9の間 print n # nを出力する }
for文はまた、配列に対して繰り返し処理を行う場合にも使用されます。
arr1[0] = "Red" arr1[1] = "Green" arr1[2] = "Blue" for (i in arr1) { print arr[i] } arr2["red"] = "#f00" arr2["green"] = "#0f0" arr2["blue"] = "#00f" for (x in arr2) { print x " = " arr2[x] }
switch文は、複数の条件分岐を行う際に使用します。case で条件を指定します。下記の例では、変数 color の値が何なのかによって処理を振り分けています。default はどの条件にもマッチしなかった場合のアクションを指定します。
switch (color) { # coloeの値が... case "red": # "red"であれば print "#f00" # "#f00"を表示 break case "green": # "green"であれば print "#0f0" # "#0f0"を表示 break case "blue": # "blue"であれば print "#00f" # "#00f"を表示 break default: # いずれでもなければ print "(unknown)" # "(unknown)"を表示 break }
break文を記述しない場合、次の条件のアクションも実行します。下記の場合、"red" や "green" の場合の break 文が無いため、"red"、"green"、または "blue" の場合に "(known)" を表示します。
switch (color) { # colorの値が case "red": # "red"でも case "green": # "green"でも case "blue": # "blue"でも print "(known)" # "(known)"を表示 break default: print "(unknown)" break }
break文は、switch文で使用する他、for、while、do-while文のループを抜ける場合に使用します。
for (i = 0; i < 10; i++) { if (i == 5) { # iが5になったら break # forループを終了する } print n }
for や while が多重にネストしている場合、一番内側のループを抜けます。
for (i = 0; i < 10; i++) { for (j = 0; j < 10; j++) { if (i == 5 && j == 5) { # iが5、jも5になったら break # 一番内側のjのループを終了する } print i, j } }
continue文は、一番内側のループを繰り返し実行します。下記の例では i が 3 の時はアクションを途中でスキップして、i = 4 のループに移ります。
for (i = 0; i < 5; i++) { if (i == 3) { # iが3であれば continue # 後続のアクションをスキップする } print i # => 0 1 2 4 }
next文は、現在のレコードに対するアクションを終了し、次のレコードの処理に移ります。
{ if (NF < 5) { # フィールドの個数(NF)が5未満であれば next # 次のレコードの処理に移る } }
nextfile文は、現在のファイルに対するアクションを終了し、次のファイルの処理に移ります。
{ if ($1 == "END") { # 第1フィールドが"END"であれば nextfile # 次のファイルの処理に移る } }
exit文はプログラムを終了させます。引数にはプログラムの終了ステータスを指定することができます。
if ($1 == "END") { # 第1フィールドが"END"であれば exit 1 # プログラムを終了する(終了ステータス=1) }
いくつかの ビルトイン関数 の他、function を用いてユーザ定義の関数を使用することができます。下記は、第1引数 x と第2引数 y を受け取り、その和を返却する関数 add() を定義し、$1 と $2 の合計を表示しています。return は関数の戻り値を指定します。
function add(x, y) { return x + y } BEGIN { print add($1, $2) }
function の代わりに省略形の func を使用することもできます。
func add(x, y) { return x + y }
ローカル変数を使用するには、引数の箇所にローカル変数を記述します。引数とローカル変数の間は慣習的に少し離して記述します。
function sum(arr, i, ret) { ret = 0; for (i = 0; i < length(arr); i++) { ret = ret + arr[i] } return ret } BEGIN { arr[0] = 123 arr[1] = 234 arr[2] = 300 print sum(arr) }
@ を用いると、文字列を関数名として使用することができます。関数名を関数の引数として受け取り、呼び出す際に便利です。
fname = "add"
print @fname(3, 5) # => 8
/ ... / で正規表現を使用することができます。正規表現の詳細は とほほの正規表現入門 を参照してください。
/ABC/ { ... } # 行全体の中にABCが含まれていれば $0 ~ /ABC/ { ... } # 行全体の中にABCが含まれていれば $1 ~ /ABC/ { ... } # 第1カラムにABCが含まれていれば $1 !~ /ABC/ { ... } # 第1カラムにABCが含まれていなければ { if ($1 ~ /ABC/) { ... } } # 第1カラムにABCが含まれていれば
下記のエスケープシーケンスを利用できます。
\\ # バックスラッシュ \a # ベル(BEL) (0x07) \b # バックスペース(BS) (0x08) \f # フォームフィード(FF) (0x0c) \n # 改行(LF) (0x0a) \r # 復帰(CR) (0x0d) \t # タブ(TAB) (0x09) \v # 垂直タブ(VT) (0x0b) \nnn # 文字コード指定(8進数) \xhh # 文字コード指定(16進数) \/ # スラッシュ(/) \" # ダブルクォート(")
下記の正規表現を使用できます。
^ # 行頭にマッチ $ # 行末にマッチ . # 任意の1文字(改行を含む)にマッチ [ABC] # AまたはBまたはCにマッチ [A-Z] # A~Zにマッチ [a-zA-Z0-9] # 半角英数字にマッチ [^ABC] # A, B, C以外の文字にマッチ A|B # AまたはBにマッチ (...) # グルーピングを行う A* # 0個以上のAにマッチ A+ # 1個以上のAにマッチ A? # 0個または1個のAにマッチ A{n} # n個のAにマッチ A{n,} # n個以上のAにマッチ A{n, m} # n~m個のAにマッチ
[...] の中では下記の POSIX表現を使用することができます。
[:alnum:] # 英数字(a-zA-Z0-9) [:alpha:] # 英字(a-zA-Z) [:lower:] # 小文字(a-z) [:upper:] # 大文字(A-Z) [:digit:] # 10進数字(0-9) [:xdigit:] # 16進文字(0-9a-fA-F) [:blank:] # 空白文字(SP,TAB) [:space:] # 空白文字(SP,TAB,LF,CR,FF,VT) [:cntrl:] # 制御文字 [:graph:] # 印字可能文字(空白を含まない) [:print:] # 印字可能文字(空白を含む) [:punct:] # 記号文字(!"#$%&'-=^~\|@`...)
下記を使用することもできます。
\s # 空白文字(TAB,LF,CR,FF,VT) \S # \s以外の文字 \w # アンダーバーを含む英数字 \W # \w以外の文字 \< # 単語の先頭 \> # 単語の末尾 \y # 単語の先頭または末尾 \B # 単語の先頭または末尾以外 \` # 文字列の先頭 \' # 文字列の末尾
正規表現(/.../)は通常はオブジェクトとして扱われないため、変数に代入しても正規表現として使用することはできません。これを実現するためには /.../ の代わりに @/.../ を使用します。
reg = @/^[A-Z]+$/ if (str ~ reg) { ... }
@include は外部ファイルをプログラムファイルとして読み取ります。ファイルを探す場所は通常カレントディレクトリですが、AWKPATH が指定されていればその場所から探します。
@include "mysubr.awk"
@load は共有ライブラリ形式のライブラリを読み込みます。
@load "ordchr"; BEGIN { print chr(0x41) }
AWK 5.0 からはネームスペースの機能が加わりました。同じ関数名であっても、下記の様に名前空間を分けて呼び出すことが可能です。
# mylibA.awk @namespace "mylibA" function myfunc(x, y) { return x + y }
# mylibB.awk @namespace "mylibB" function myfunc(x, y) { return x * y }
@include "mylibA.awk" @include "mylibB.awk" BEGIN { print mylibA::myfunc(3, 5) # mylibA.awkのmyfunc() print mylibB::myfunc(3, 5) # mylibB.awkのmyfunc() }
コマンドラインには下記のオプションや引数を指定できます。
いくつかのビルトイン変数を使用することができます。下記の例ではフィールドセパレータ(FS) をカンマ(,)としてCSV ファイルを読み込み、そのフィールド数(NF)を出力しています。
$ awk '{ print NF }' FS=, data.csv $ awk -v FS=, '{ print NF }' data.csv $ awk 'BEGIN { FS="," } { print NF }' data.csv
ビルトイン変数には下記のものがあります。
下記のビルトイン関数を使用できます。個々の関数の詳細説明は省略します。
# 数学関連 int(x) # xの整数部 rand() # 0.0~1.0の間の乱数 srand(x) # 乱数の初期シードを指定(xを省略すると現時刻をシードとする) sqrt(x) # 0.0~1.0の間の乱数 exp(x) # xの平方根 sin(x) # xのサイン cos(x) # xのコサイン atan2(y, x) # y/xのアークタンジェント log(x) # log x # 文字列関連 asort(arr[, dest[, how]]) # 値順にソート asorti(arr[, dest[, how]]) # 添え字(インデックス)順にソート gensub(reg, replace, how[, target]) # 文字列を高度に置換 gsub(reg, replace[, target]) # 文字列を連続置換 index(str, s) # str中にsが出現する位置 length([str]) # strの長さ match(str, reg[, array]) # strが正規表現regにマッチするかを検査 patsplit(str, array[, fpat[, seps]]) # strをパターンで分割 split(str, array[, fpat[, seps]]) # strをパターンで分割 sprintf(fmt, exp1, ...) # 値をフォーマットに合わせて整形 strtonum(str) # 文字列を数値に変換 sub(reg, repl[, target]) # 文字列を置換 substr(str, start[, length]) # strの一部を抽出 tolower(str) # 小文字に変換 toupper(str) # 大文字に変換 # 入出力関連 close(filename[, how]) # ファイルをクローズ fflush([filename]) # 書き込みをフラッシュ system(command) # 外部コマンドを実行 # 時間関連 mktime(datespec[, utcflag]) # 文字列型時刻を数値型時刻に変換 strftime([fmt[, time[, utc]]]) # 数値型時刻を文字列型時刻に変換 systime() # 現在の時刻を数値型時刻で取得 # ビット操作関連 and(x1, x2, ...) # 論理積(AND) or(x1, x2, ...) # 論理和(OR) xor(x1, x2, ...) # 排他的論理和(XOR) compl(x) # 補数 lshift(x, n) # 左シフト rshift(x, n) # 右シフト # 型情報関連 isarray(x) # 配列か否かを確認 typeof(x) # 型名を取得 # 国際化対応関連 bindtextdomain(directory[, domain]) # ドメインのパスを設定 dcgettext(directory[, domain[, category]]) # 単一の参照に関するドメインを上書き dcngettext(str1, str2, n[, domain[, category]]) # 単一の参照に関するドメインを上書き(複数)
ビルトイン関数の他にも @load または -i や -l オプションで読み込むライブラリ機能があります。
@load "filefuncs" chdir(directory) # カレントディレクトリを移動 stat(file, statdata[, follow]) # ファイル情報を得る flags = or(FTS_PHYSICAL, ...) # fts()に渡すフラグを生成 fts(pathlist, flags, filedata) # ディレクトリを横断検索する? @load "fnmatch" fnmatch(pattern, filename, flags) # filenameがワイルドカードpatternにマッチするか調べる @load "fork" pid = fork() # プロセスをフォークする waitpid(pid) # 指定した子プロセスの終了を待つ wait() # いずれかの子プロセスの終了を待つ @load "inplace" # -i inplaceで読み込むと入力ファイルを書き換える @load "ordchr" number = ord(string) # 文字を文字コードに変換 char = chr(number) # 文字コードを文字に変換 @load "readdir" # ディレクトリ内のファイル一覧?(うまく動かない) BEGIN { FS = "/" } { print "file name is", $2 } @load "revoutput" # "/dev/stdout"への書き込みを逆順にする BEGIN { REVOUT = 1 } { print $0 > "/dev/stdout" } @load "rwarray" writea(file, arr) # 配列をバイナリデータとしてファイルに格納する reada(file, arr) # writea()で書き込まれたデータを配列として読み出す @load "readfile" readfile(file) # ファイルの内容を一括して読み込む BEGIN { PROCINFO["readfile"] = 1 } # $0とRTを設定するらしいがうまく機能しない @load "time" gettimeofday() # 1970年1月1日00:00:00からの秒数を得る sleep(sec) # sec秒間スリープする
下記の環境変数が参照されます。
AWK でネットワークアクセスすることも可能です。下記は簡単な TCP サーバの例です。
BEGIN { print "Hello!" |& "/inet/tcp/8080/0/0" close("/inet/tcp/8080/0/0") }
次は簡単な TCP クライアントの例です。上記の TCP サーバに接続して Hello! メッセージを取得して表示します。
BEGIN { "/inet/tcp/0/localhost/8080" |& getline print $0 close("/inet/tcp/0/localhost/8080") }
次は簡単な HTTP クライアントの例です。
BEGIN { RS = ORS = "\r\n" http = "/inet/tcp/0/www.example.com/80" print "GET http://www.example.com/" |& http while ((http |& getline) > 0) print $0 close(http) }