移動先 先頭, , , 末尾 セクション, 目次.

組込み関数

組み込み関数とはawkプログラムで常に呼び出す事のできる関数である。 この章ではawkの全ての組み込み関数を定義する。一部のものは別のセクショ ンで説明がされているが、便宜のためここでも簡単にまとめてある。 (ユーザーは自分で新たに関数を定義する事もできる セクション ユーザー定義関数を参照.)

組込み関数の呼び出し

組み込み関数を呼び出すには、関数の名前に続けて括弧で囲まれた引数を書けばよい。 例えばatan2(y + z, 1)は関数atan2 を二つの引数で呼び出す。

組み込み関数の名前と、開き括弧の間にある空白は無視される。しかし、そういった 空白は使わないようにすることを勧めたい。ユーザー定義の関数ではこのような空白 を許されておらず、関数名の直後に空白をおかないという単純なやり方でそのような 間違いを簡単に見つけ出せる。

組み込み関数はそれぞれ、特定の数の引数を受け取る。多くの場合、組み込み関数に 対して余計に多く渡された引数は無視される。引数が省略されたときのデフォルトの 扱いは個々の関数毎に決められている。

関数が呼び出されるとき、関数の実引数は実際に関数が呼び出される前に完全に評価 され、式が作り出される。例えば次のようなコードでは

i = 4
j = sqrt(i++)

変数iは、sqrtに対する実引数の値として4がセットされて関数が呼ば れる前に 5がセットされる。

組込みの数値関数

次に組み込み関数の全リストを挙げる。

int(x)
この関数はxを0の方に丸めた整数を返す。つまり、0とxの間にある整数 の中でもっともxに近い整数を返す。 例えば、int(3) は 3、 int(3.9) は 3、 int(-3.9) は -3、そして int(-3) は -3 となる。
sqrt(x)
この関数はxの正の平方根を返す。 xが負であった場合にはエラーとな る。したがって、sqrt(4)は2である。
exp(x)
これは自然対数eのx乗を返すか、xが範囲外であればエラーをレポート する。 xの取り得る値の範囲はあなたが使っているマシンの浮動小数点数の実 装による。
log(x)
xが正の場合にはxの自然対数を返し、そうでない場合にはエラーとなる。
sin(x)
xの正弦を返す(xの単位はラジアン)。
cos(x)
xの余弦を返す(xの単位はラジアン)。
atan2(y, x)
y / xのアークタンジェントを返す(単位はラジアン)。
rand()
乱数を返す。randの返す値は0から1の範囲の数であり、0と1は含まれない。 しばしば整数の乱数を必要とするだろうが、次に n未満の非負の整数の乱数を 返すユーザー定義関数を挙げる。
function randint(n) {
     return int(n * rand())
}
この例では、掛け算で0より大きくn未満の実数を作り出す。それを(int を使って)0からn - 1の間の整数にする。 次の例は先ほどのものと同じ様な1からnの間の整数を返す関数を使っている。 このプログラムはレコード入力の度に新しい乱数を出力する。
awk '
# サイコロをシミュレートする関数
function roll(n) { return 1 + int(rand() * n) }

# 三つの六面体サイコロを振り、合計を出力する
{
      printf("%d ポイント\n", roll(6)+roll(6)+roll(6))
}'
ノート:awkを走らせるたびにrandは、同じ場所、もしくは seedから数値を作り出す。このことはプログラムを実行する度に同じ結果が生 成されるということである。その数値はひとつのawkプログラムの中ではラン ダムであるけれども走らせるごとに予想できるものである。これはデバッグには便利 であるけれども、使う度毎に違う結果を必要とするような場合には実行する毎に乱数 の種を違ったものにしなければならない。それを行うにはsrandを使用する。
srand(x)
srandは乱数を生成するための出発点、もしくはの値として xをセットする。 それぞれの種は各々特定の"乱数列"を導き出す。従って、乱数の種として同じ値を 二度目にセットしたとすると、同じ"乱数列"を得ることになる。 srand()の引数xを省略した場合、乱数の種としてその時点の日時が使 用される。この方法は予測できないような乱数列を得られる。 srandの返す値は以前使われていた乱数の種である。これによって以前の乱数 系列をもう一度作り出すことが簡単になる。

組込みの文字列操作関数

このセクションにある関数は一つ以上の文字列を検索したり変更したりするものである。

index(in, find)
文字列inの中で、findが出てくる最初の場所を検索し、見つかった文字 列が始まるinのキャラクタの位置を返す。例えば、
awk 'BEGIN { print index("peanut", "an") }'
`3'を出力する。findが見つからなかった場合、indexは0を返す。 (awkでの文字列の添字は1から始まると言うことを思い出して欲しい)
length(string)
string中のキャラクタの数を返す。 stringが数値であった場合、その 数値を(その数値を表す)文字列に変換したときのキャラクタの数が返る。例えば、 length("abcde")は5であるが、length(15 * 35)の結果は 3である。 それは15 × 35 = 525で、この525は三つのキャラクタからなる `"525"'という 文字列に変換されるからである。 引数が省略された場合、length$0の長さを返す。 古いバージョンのawkでは、length関数を括弧なしで呼ぶことができ る。しかしそれは、 POSIX の標準では好ましくない(deprecated)とされる。このことは、プログラム中 でこういった書き方が将来のバージョンでは使えなくなるかも知れないということで ある。従って、awkプログラムの移植性を最大にするために括弧を常に書くべ きである。
match(string, regexp)
match関数はstringから、正規表現regexpにマッチする部分文字 列の中で、最も左にあり、もっとも長い部分文字列を検索し、部分文字列が始まる場 所を返す(stringの最初から始まっていれば1)。マッチするものが見つから なかった場合、0が返る。 match関数は組み込み変数のRSTART にインデックスをセットし、同様 に組み込み変数RLENGTHにマッチした部分文字列の長さをセットする。マッチ しなかった場合には、RSTART には0が、RLENGTH には -1がセッ トされる。 例えば、
awk '{
       if ($1 == "FIND")
         regex = $2
       else {
         where = match($0, regex)
         if (where)
           print "Match of", regex, "found at", where, "in", $0
       }
}'
このプログラムは変数regexに格納されている正規表現にマッチする行を探す。 この正規表現は変更することができる。ある行の最初の単語が`FIND'であった 場合、 regexはその行の二番目の単語に変更される。従って、次のようなデー タを与えると
FIND fo*bar
My program was a foobar
But none of it would doobar
FIND Melvin
JF+KM
This line is property of The Reality Engineering Co.
This file created by Melvin.
awk は次のように出力する:
Match of fo*bar found at 18 in My program was a foobar
Match of Melvin found at 26 in This file created by Melvin.
split(string, array, fieldsep)
この関数はstringfieldsepによって分割し、分割された結果を arrayに格納する。分割された最初の要素はarray[1]に、二番目 の要素は array[2]に格納され、以下の要素も同様である。三番目の引 数fieldsepの文字列値は、 stringを分割する場所を指定する (FSが入力レコードを分割する場所にマッチする正規表現であるように)正 規表現である。 fieldsepが省略されると、FSの値が使われる。 splitは作り出された要素の数を返す。 split関数はまた、入力行をフィールドに分割するとの同じ様なやり方で文字 列を分割する。例えば、
split("auto-da-fe", a, "-")
これは`-'をセパレータとして、`auto-da-fe'という文字列を三つのフィ ールドに分割し、配列aの要素を以下のようにセットする。
a[1] = "auto"
a[2] = "da"
a[3] = "fe"
splitを呼び出して返ってくる値は3である。 入力フィールドを分割するときと同じ様に、fieldsepの値が" " であ る場合には先頭や末尾にある空白は無視され、要素は空白で区切られる。
sprintf(format, expression1,...)
この関数はprintfがその引数を渡されたときに出力するであろう文字列を (出力はせずに)返す。 (セクション printf文を使った Fancier Printingを参照). 例えば、
sprintf("pi = %.2f (approx.)", 22/7)
これは"pi = 3.14 (approx.)"という文字列を返す。
sub(regexp, replacement, target)
sub関数はtargetの値を変更する。検索する値は文字列でなければなら ず、そしてそれは regexpで与えられる正規表現にマッチする部分文字列の中 で一番左にあり、長さが一番長いものである。文字列全体の内マッチしたテキストは replacementで置き換えられる。 この関数は独特である。それは、targetが単に値を計算するのに使われるので はなく、式ではないということからくる。 targetは変数、フィールド、配列 の参照のように変更された値を格納できるものでなければならない。この引数が省略 された場合にはデフォルトとして$0が使用される。 例を挙げると
str = "water, water, everywhere"
sub(/at/, "ith", str)
この例は str"wither, water, everywhere"をセットし、その 中で最も左にあり、もっとも長い`at'`ith'に置き換える。 sub関数は置き換えを行った数(つまり1か0のいずれか)を返す。 replacement中にスペシャルキャラクタ`&'があると、それはregexp にマッチした部分文字列を表す。 (もしこの正規表現が二つ以上の文字列にマッチす るのならば、 `&'が表す部分文字列が変化するだろう) 例えば、
awk '{ sub(/candidate/, "& and his wife"); print }'
各入力行で最初に現れる`candidate'`candidate and his wife'に 変更する。 別の例を挙げよう。
awk 'BEGIN {
        str = "daabaaa"
        sub(/a*/, "c&c", str)
        print str
}'
この例では`dcaacbaaa'が出力される。これは`&'は非文字定数として扱わ れ、最左最長の規則に従っている為である。 スペシャルキャラクタ(`&')の効果はその前にバックスラッシュを付けることに よって抑制することができる。例によって、文字列中に一つのバックスラッシュを入 れるためにはバックスラッシュを二つ続けて書かなければならない。従って、置換文 字列中に`&'という文字を含ませるには`\\&'と記述する。次に挙げる例は 各行で最初に現れる`|'`&'で置き換える。
awk '{ sub(/\|/, "\\&"); print }'
ノート:上述のように、subの三番目の引数は左辺値でなければならな い。一部のawkには三番目の引数として左辺値でない式を許すものもある。そ ういった場合、subはパターンを検索し、0か1を返すけれども、置き換え(起 こったとして)の結果は、それを格納する場所がないので失われる。そのような awkは次のような式を受け付ける。
sub(/USA/, "United States", "the USA and Canada")
しかしこれはgawkではエラーとなる。
gsub(regexp, replacement, target)
この関数はsubと似ているが、gsubはもっとも長く、最も左にあり、 それぞれが重ならないようなマッチした部分文字列をすべて置換する。 gsub`g'は全ての場所で置換を行う"global"を意味する。次の例で は、
awk '{ gsub(/Britain/, "United Kingdom"); print }'
全ての入力レコードで、`Britain'という文字列を全て `United Kingdom' に置き換える。 gsub関数は置き換えが起こった回数を返す。検索と置換の対象となる変数 targetが省略された場合、入力レコード全体、つまり$0が使用される。 subと同じ様に、`&'`\'の二つのキャラクタは特殊な意味があ り、また三番目の引数は左辺値でなければならない。
substr(string, start, length)
この関数はstring中でstart番目のキャラクタから始まる長さ lengthの部分文字列を返す。文字列の最初のキャラクタの数は1である。例え ば、substr("washington", 5, 3)"ing"を返す。 lengthが与えられない場合、この関数はstringstart番目から 始まる残りの部分全てを返す。例えば、substr("washington", 5)"ington"を返す。 lengthstart番目から文字列の終端までの 長さよりも長い場合も同様である。
tolower(string)
この関数は与えられたstring中の大文字を小文字に置き換えた文字列を返す。 このときアルファベット以外のキャラクタは変更されない。例えば、 tolower("MiXeD cAsE 123")"mixed case 123"を返す。
toupper(string)
この関数は与えられたstring中の小文字を大文字に置き換えた文字列を返す。 このときアルファベット以外のキャラクタは変更されない。例えば、 toupper("MiXeD cAsE 123")"MIXED CASE 123"を返す。

入出力の組込み関数

close(filename)
filenameで指定される入力ファイルや出力ファイルをクローズする。 引数は、パイプに入出力するために使用したシェルコマンドであってもよく、 その場合はパイプがクローズされる。 セクション 入力ファイルやパイプのクローズを参照, に入力ファイルや入力パイプのクローズに関する記述があり、 input files and pipes. セクション 出力ファイルやパイプのクローズを参照, に出力ファイルや出力パイプのクローズに関する記述がある。
system(command)
system関数は、ユーザーがオペレーティングシステムのコマンドを実行し、その後に awkプログラムに復帰するという動作を行うことを許す。 system関数 は文字列commandで指定されるコマンドを実行する。その戻り値はコマンドが実 行されたときのリターンステータスである。 例えばawkプログラム中に次のようなコードを記述すると、
END {
     system("mail -s 'awk run done' operator < /dev/null")
}
システムオペレータは awkプログラムが入力の処理を終了し、入力終了時の 処理を始めるときにメイルを送信する。 同様な結果をprintprintfをパイプにリダイレクトすることで得 ることもできるが、awkプログラムが対話的であるような場合に、system はシェルやエディタのような大きな実行プログラムを起動するのに便利である。 一部のオペレーティングシステムではsystem関数を実装できない。 サポートされていない場合、systemは致命的エラーを引き起こす。

Controlling Output Buffering with system

多くのユーティリティプログラムはその出力をバッファリングしていて、ディ スク上のファイルや、ターミナルに出力する情報を、一回のオペレーションで出力す るのに充分な量になるまで保存している。このことは細かな(出力する)情報が来る 度にいちいち書き出しを行うのに比べてより効果的である。しかし、時としてプログ ラムに対して強制的にそのバッファを、例えバッファがいっぱいになっていなくても フラッシュさせる(そのバッファが対応している出力先に対して出力する)必 要がある場合もある。そのようなときはawkプログラム中でsystemの 引数を空文字列にして呼び出しを行えばよい。

system("")   # 出力のフラッシュ

gawkはこのようなsystem関数の使い方を特殊なものとして扱い、空の コマンドでシェル(あるいは他のインタプリタ)を走らせるようなことはしない。従っ て、gawkではこのような使い方は便利なだけでなく、この使い方が他のイン プリメンテーションのawkでも同様に働くのであれば、必要のないシェルを実 行する必要もなくなる。

タイムスタンプを扱う関数

awkプログラムの一般的な使い方はログファイルの処理である。ログファイル はしばしば、ある特定のレコードが書き込まれたタイムスタンプの情報を持っている。 多くのプログラムはtimeシステムコールが返した値(ある特定の時点からの経 過秒数)をタイムスタンプに使っている。 POSIX システムでは、それは UTC 1970年 の1月1日0時からの秒数である。

ログファイル等の処理や便利なレポートの作成を簡単にするために、 gawkは タイムスタンプに関連した働きをする二つの関数を備えている。これら二つは両方と もgawk特有の拡張であり、POSIX 標準では定義されていないし、ほかの awkでも使うことはできない。

systime()
この関数はシステムが始まった(?)時点から現在までの時間を秒で返す。 POSIX のシ ステムでは、これは1970年1月1日の0時を機転としている。これは他のシステムでは 恐らく違った数字であろう。
strftime(format, timestamp)
この関数は文字列を返す。この関数は ANSI のC標準ライブラリの同名の関数と同じ ものである。timestampで特定される時間を文字列にするのに使い、文字列 formatをベースに文字列化する。

systime関数はログファイルの日付、時間と、プログラムを実行している時点 の日付、時間とを比較することを可能にする。特に、ある特定のレコードが記録され てからどれくらいたったのかを求めることが簡単になる。それはまた、"seconds since the epoch"フォーマットを使ってログのレコードを作成することを可能にす る。

strftime関数はタイムスタンプを、人間が読み易い情報に変換するのを簡単 にさせる。この関数はsprintfと似ていて、書式指定でないキャラクタはその まま文字列として返され、書式指定文字列中で日付や時刻を特定するものがあるとそ れを置き換える。もし、timestampが省略されると gawkは代わりに実 行時の時間を使う。

strftimeは、ANSI の標準Cがサポートする以下の書式指定を使用できる。

%a
実行されている環境での曜日の略称。
%A
実行されている環境での省略なしの曜日の名称。
%b
実行されている環境での、月の省略名称。
%B
実行されている環境での、省略なしの月の名前。
%c
実行されている環境での"適当な"日付と時刻の表示形式。
%d
十進数で表わした月の日数(01から31まで)。
%H
24時間表示での時刻(00から23まで)。
%I
12時間表示での時刻(01から12まで)。
%j
その年の初めからの日数(001から366まで)。
%m
月(01から12まで)。
%M
分(00から59まで)。
%p
実行されている環境での、12時間表示の時の午前/午後を表わすもの。
%S
秒(00から61まで)。(うるう秒のために0から61までになっている)
%U
第何週かを示す数値(最初の日曜日が第一週の最初の日である。範囲は00から53)。
%w
曜日を表わす数値。0から6までの範囲で、日曜日が0。
%W
第何週かを示す数値(最初の月曜日が第一週の最初の日である。範囲は00から53)。
%x
実行されている環境での"適当な"日付表示。
%X
実行されている環境での"適当な"時間表示。
%y
世紀を除いた年(00から99まで)。
%Y
世紀を含めた年
%Z
タイムゾーンの名前かその略称、あるいはタイムゾーンが決定できなければ空。
%%
`%'という文字。

もし変換指定文字が上に挙げたもののひとつでない場合には、その結果は未定義であ る。 (これは ANSI の標準CではCバージョンのstrftimeのそのような場合の 動作が定義されていないからで、gawkが使うであろうそのシステムでの strftimeそれならば同様の結果となる。典型的なのは変換指定文字が戻り値の 文字列にないということだろう。)

非公式に、 localeはプログラムを実行する地理的な場所である。例えば、ア メリカ合衆国では1991年9月4日を略して書き表わす普通のやり方は "9/4/91"であ る。ヨーロッパの多くの国ではそれを"4.9.91"のように記述する。したがって、ア メリカにおいては`%x'という指定は `9/4/91'という結果となり、ヨーロッ パでは`4.9.91'という結果となる。 ANSI 標準Cでは大部分のCプログラマーが 使うであろう環境でのデフォルトのCのロカール(locale)を定義している。

パブリックドメインバージョンのstrftimeは ANSIに完全にしたがった形では 書かれていない。そういったものをgawkのコンパイルのときに使用すれば (セクション gawkのインストールを参照.)、次に挙げるような書式指定も 行なうことが可能である。

%D
`%m/%d/%y'という指定に等しい。
%e
月のなかでの日だが、一桁の場合には空白を補う。
%h
`%b'と同じ。
%n
改行キャラクタ()ASCII のLF)。
%r
`%I:%M:%S %p'という指定と同じ。
%R
`%H:%M'という指定と同じ。
%T
`%H:%M:%S'という指定と同じ。
%t
タブ。
%k
24時間表示での時刻を十進表記で表わしたもの(0-23)。 一桁の場合には空白が付け加えられる。
%l
12時間表示での時刻を十進表記で表わしたもの(1-12)。 一桁の場合には空白が付け加えられる。
%C
00から99で表わした年(西暦の下二桁)。
%u
月曜日を1で表わした、曜日を表わす数値(1(月曜)から7まで)。
%V
最初の月曜日を1とした週(01から53まで)。 週の数値を決めるやり方はISO 8601で定められている。 (すなわち、1月1日がある週が(1月1日から)、4日以上あるのであれば その週が1。そうでなければその週は53となり、次の週が1となる。)
%Ec %EC %Ex %Ey %EY %Od %Oe %OH %OI
%Om %OM %OS %Ou %OU %OV %Ow %OW %Oy
(These facilitate compliance with the POSIX date utility.)これらは"代替表現"(alternate representations)であり、 二番目の文字((`%c'`%C'など)だけが指定に使われる。 これらは認識されるが、それらの通常の意味が使用される (これらはPOSIXのdateユーティリティに従うことを容易にする)。
%v
VMSフォーマットでの日付(例 20-JUN-1991)。

次の例はstrftimeを使った例である。 最初がCのctime関数のawkバージョンである。 (これはユーザー定義関数である。 セクション ユーザー定義関数を参照.)

# ctime.awk
#
# awk による Cライブラリの ctime(3) 関数

function ctime(ts,    format)
{
    format = "%a %b %e %H:%M:%S %Z %Y"
    if (ts == 0)
        ts = systime()         # デフォルトとして現在時刻を使う
    return strftime(format, ts)
}

次の例は、POSIX のdateユーティリティの awkによる実装 である。通常は、dateユーティリティは現在の日付と時刻をよく使わ れる書式で出力する。しかしながら、`+'で始まる引数を与えた場合には、 dateは書式指定でない文字列を書式指定の文字がくるまでそのまま標準出力 に送る。たとえば、

date '+Today is %A, %B %d, %Y.'

これは次のような出力を行なう。

Today is Thursday, July 11, 1991.

awk バージョンの dateユーティリティはこうなる。

#! /usr/bin/gawk -f
#
# date -- P1003.2 Draft 11 の'date' コマンドの実装
#
# Bug: -u 引数を認識しない。

BEGIN    \
{
    format = "%a %b %e %H:%M:%S %Z %Y"
    exitval = 0

    if (ARGC > 2)
        exitval = 1
    else if (ARGC == 2) {
        format = ARGV[1]
        if (format ~ /^\+/)
            format = substr(format, 2)    # 先行する+を取り除く
    }
    print strftime(format)
    exit exitval
}

移動先 先頭, , , 末尾 セクション, 目次.