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

組み込み関数

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

Calling Built-in Functions

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

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

組み込み関数はそれぞれ、特定の数の引数を受け取る。多くの場合、組み込み関 数に対して余計に多く渡された引数は無視される。引数が省略されたときのデフ ォルトの扱いは個々の関数毎に決められている。一部のawk処理系では、 組込み変数に余計な引数を渡した場合はそういった引数は無視されていた。しか しawkでは、それは致命的なエラーとなる。

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

i = 4
j = sqrt(i++)

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

関数に対する実引数を評価する順番は定義されていない。そのため、 実引数が左から右へ順番に評価されるということを仮定したプログラムを 書くべきではない。例えば、

i = 5
j = atan2(i++, i *= 2)

上記のようなプログラム片があったとして、評価の順番が左から右であったとす ると、iは最初に6になり、ついで12となり、それからatan2が実 引数6と12で呼び出されるしかし、評価が右から左へ行われたとすると、@code {i}は最初に10となり、ついで11になる。その後atan2の呼び出しが実引 数11と10で行われる。

Numeric Built-in Functions

以下のリストは、数値を扱うすべての組込み関数である。 省略可能な引数はブラケット("[" と "]")で囲まれている。

int(x)
この関数は整数への丸めを行う。 丸めのときは0へ向かって、つまり0と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の自然対数を返し、そうでない場合にはエラーとなる。l
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 points\n",
             roll(6)+roll(6)+roll(6))
}'
注意:gawkも含めて、大部分のawk処理系では実行の度 にrandは、同じ数値、もしくはから数値を作り出しはじめる。 このことはプログラムを実行する度に同じ結果が生成されるということである。 その数値はひとつのawkプログラムの中ではランダムであるけれども走ら せるごとに予想できるものである。これはデバッグには便利であるけれども、使 う度毎に違う結果を必要とするような場合には実行する毎に乱数の種を違ったも のにしなければならない。それを行うにはsrandを使用する。
srand([x])
srandは乱数を生成するための出発点、もしくはの値として xをセットする。 それぞれの種は各々特定の"乱数列" (11) を導き出す。従って、乱数の種として同じ値を 二度目にセットしたとすると、同じ"乱数列"を得ることになる。 srand()の引数xを省略した場合、乱数の種としてその時点の日時が使 用される。この方法は予測できないような乱数列を得られる。 srandの返す値は以前使われていた乱数の種である。これによって以前の乱数 系列をもう一度作り出すことが簡単になる。

Built-in Functions for String Manipulation

このセクションにある関数は一つ以上の文字列を検索したり変更したりするものである。 省略可能な引数はブラケット("[" と "]")で囲まれている。

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 != 0)
           print "Match of", regex, "found at", \
                     where, "in", $0
       }
}'
このプログラムは変数regexに格納されている正規表現にマッチする行を探す。 この正規表現は変更することができる。ある行の最初の単語が`FIND'であった 場合、 regexはその行の二番目の単語に変更される。従って、次のようなデー タを与えると
FIND ru+n
My program runs
but not very quickly
FIND Melvin
JF+KM
This line is property of Reality Engineering Co.
Melvin was here.
awkの出力は次のようになる。
Match of ru+n found at 12 in My program runs
Match of Melvin found at 1 in Melvin was here.
split(string, array [, fieldsep])
この関数はstringfieldsepによって分割し、分割された結果を arrayに格納する。分割された最初の要素はarray[1]に、二番目 の要素は array[2]に格納され、以下の要素も同様である。三番目の引 数fieldsepの文字列値は、 stringを分割する場所を指定する (FSが入力レコードを分割する場所にマッチする正規表現であるように)正 規表現である。 fieldsepが省略されると、FSの値が使われる。 splitは作り出された要素の数を返す。 split関数はまた、入力行をフィールドに分割するとの同じ様なやり方で文字 列を分割する。例えば、
split("cul-de-sac", a, "-")
これは`-'をセパレータとして、`auto-da-fe'という文字列を三つのフィ ールドに分割し、配列aの要素を以下のようにセットする。
a[1] = "cul"
a[2] = "de"
a[3] = "sac"
splitを呼び出して返ってくる値は3である。 入力フィールドを分割するときと同じ様に、fieldsepの値が" " であ る場合には先頭や末尾にある空白は無視され、要素は空白で区切られる。 また同様に、fieldsepが空文字列であれば、個々のキャラクタが配列の要 素となるように分割がおこなわれる(これはgawk特有の拡張である)。 最近のgawk処理系では、gawkも含めて、この関数の第三引数に文 字列だけでなく(/abc/)のような正規表現定数を許している。(d.c.) POSIXの標準も同様である。 文字列の分割に先立って、splitは配列arrayの 要素をすべて削除する(d.c.) stringのどこにもfieldsepにマッチするものがない場合、 arrayは一つの要素を持つようになる。その要素の値は、 元々のstringと同じである。
sprintf(format, expression1,...)
この関数はprintfがその引数を渡されたときに出力するであろう文字列を (出力はせずに)返す。 (セクション Using printf Statements for Fancier Printingを参照). 例えば、
sprintf("pi = %.2f (approx.)", 22/7)
returns the string "pi = 3.14 (approx.)". これは"pi = 3.14 (approx.)"という文字列を返す。
sub(regexp, replacement [, target])
sub関数はtargetの値を変更する。検索する値は文字列でなければなら ず、そしてそれは regexpで与えられる正規表現にマッチする部分文字列の中 で一番左にあり、長さが一番長いものである文字列全体の内マッチしたテキストは replacementで置き換えられる。 置き換えられた文字列はtargetの新しい値となる。 この関数は独特である。それは、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
この例では`dcaacbaaa'が出力される。これは`&'は非文字定数として扱わ れ、"最左最長"の規則に従っている為である。 (セクション How Much Text Matches?を参照)。 スペシャルキャラクタ(`&')の効果はその前にバックスラッシュを付けることに よって抑制することができる。例によって、文字列中に一つのバックスラッシュを入 れるためにはバックスラッシュを二つ続けて書かなければならない。従って、置換文 字列中に`&'という文字を含ませるには`\\&'と記述する。次に挙げる例は 各行で最初に現れる`|'`&'で置き換える。
awk '{ sub(/\|/, "\\&"); print }'
ノート:上述のように、subの三番目の引数は左辺値でなければならな い。一部のawk処理系には三番目の引数として左辺値でない式を許すものもある。 そういった場合、subはパターンを検索し、0か1を返すけれども、置き換え(起 こったとして)の結果は、それを格納する場所がないので失われる。そのような awkは次のような式を受け付ける。
sub(/USA/, "United States", "the USA and Canada")
過去のものに対する互換性のために、gawkはこのような間違ったコード を受容する。しかしながら、第三引数として別の変更不能なオブジェクトを 使った場合には致命的エラーを引き起こす結果となり、プログラムを実行する ことができないだろう。 結局のところ、regexpは正規表現定数ではなく、文字列へと変換され その文字列値がマッチすべき正規表現として取り扱われるものである。
gsub(regexp, replacement [, target])
この関数はsubと似ているが、gsubはもっとも長く、最も左にあり、 それぞれが重ならないようなマッチした部分文字列をすべて置換する。 gsub`g'は全ての場所で置換を行う"global"を意味する。次の例で は、
awk '{ gsub(/Britain/, "United Kingdom"); print }'
全ての入力レコードで、`Britain'という文字列を全て `United Kingdom' に置き換える。 gsub関数は置き換えが起こった回数を返す。検索と置換の対象となる変数 targetが省略された場合、入力レコード全体、つまり$0が使用される。 subと同じ様に、`&'`\'の二つのキャラクタは特殊な意味があ り、また三番目の引数は左辺値でなければならない。
gensub(regexp, replacement, how [, target])
gensubは汎用的な置換関数である。subgsubのように 対象文字列targetから正規表現regexpに マッチする部分を検索する。subgsubと違うのは、 関数の戻り値として置換が行われた文字列を返し、 元の文字列を変更しないという点である。 もしhow`g'`G'で始まる文字列であれば、 regexpにマッチする全てのものをreplacementに置き換え、 そうでない場合には howは何番目にマッチしたものを regexpで置き換える かを指示する。 targetが渡されなかった場合、$0が代わりに 使われる。 gensubには、 置換テキストの中で正規表現の構成要素を指定する というsubgsubにはない機能 が追加されている。 これはマークする正規表現を括弧で囲み、置換テキスト の中で`\n'を使って指定する。 nは1から9までの数字である。 例えば、
$ gawk '
> BEGIN {
>      a = "abc def"
>      b = gensub(/(.+) (.+)/, "\\2 \\1", "g", a)
>      print b
> }'
-| def abc
subで説明したように、文字列中でバックスラッシュを一つ 置くためには、二つタイプしなければならない。 置換テキスト中では、`\0'`&'と同じように マッチしたテキスト全体を表わす。 次の例は、三番目の引数を置き換えの対象となる (正規表現にマッチした)テキストを指定するために どのように使うかを表わしている。
$ echo a b c a b c |
> gawk '{ print gensub(/a/, "AA", 2) }'
-| a b c AA b c
この場合、$0がデフォルトの(置き換えの)対象文字列として 使用される。gensubは置き換えを行った結果の新しい 文字列を戻り値として返し、それは直接printで出力する ものとして(printに)渡される。 もし引数how`g'でも`G'でも始まっていない 文字列や、0よりも小さい数値であったとすると、 一度だけ置換が行われる。 regexptargetにマッチしなかった場合、gensubの 戻り値は元の値であり、targetを変更することはない。 gensubgawkの拡張であり、 互換モード(セクション コマンドラインオプションを参照)では 使用できない。
substr(string, start [, length])
この関数はstring中でstart番目のキャラクタから始まる長さ lengthの部分文字列を返す。文字列の最初のキャラクタの数は1である。例え ば、substr("washington", 5, 3)"ing"を返す。 lengthが与えられない場合、この関数はstringstart番目から 始まる残りの部分全てを返す。例えば、substr("washington", 5)"ington"を返す。 lengthstart番目から文字列の終端までの 長さよりも長い場合も同様である。 注意:substrが返す文字列に代入することはできない。 したがって、以下に示す例のようにして文字列の一部を変更しようとすることは 間違いである。
string = "abcdef"
# "abCDEf"を得ようとしているが、うまく行かない
substr(string, 3, 3) = "CDE"
また、subgsubの第三引数としてsubstrを使うのも 間違いである。
gsub(/xyz/, "pdq", substr($0, 5, 20))  # 間違い
tolower(string)
この関数は与えられたstring中の大文字を小文字に置き換えた文字列を返す。 このときアルファベット以外のキャラクタは変更されない。例えば、 tolower("MiXeD cAsE 123")"mixed case 123"を返す。
toupper(string)
この関数は与えられたstring中の小文字を大文字に置き換えた文字列を返す。 このときアルファベット以外のキャラクタは変更されない。例えば、 toupper("MiXeD cAsE 123")"MIXED CASE 123"を返す。

More About `\' and `&' with sub, gsub and gensub

sub, gsub, gensubを使っているときに バックスラッシュやアンパサンド(&)を使おうとするときは、 これらの文字が幾つかの段階で エスケープ処理(escape processing)される ことに注意する必要がある。

第一に、awkがプログラムを読み込んで 内部にプログラム実行のためのコピーを作るときに 単語レベル(lexical level)で。

さらに、awkが生成する置換文字列を実際にスキャンするときに 実行時レベル(run-time level)で。

これらの両方のレベルで、awkはバックスラッシュの後に来ることのでき るキャラクタの集合を検索する。レキシカルレベルでは、セクション エスケープシーケンスを参照. に挙げられているようなエスケープシーケンスの検索をする。した がって、awkが実行時レベルで`\'を処理するには、レキシカルレベ ルで二つの`\'をタイプする。エスケープシーケンスとして正しくないキャ ラクタが`\'の後に来たときは、UNIXのawkgawkの両方と も単純に`\'を取り去って、その後のキャラクタを文字列に送る。 だから、"a\qb""aqb"のように扱われる。

実行時レベルでは、幾つかの関数が`\'`&'のシーケンスを違ったや り方で扱う。この状況は(残念だが)ちょっとばかり複雑である。

伝統的にsubgsubという関数は、`\&'というキャラクタ 二つの並びを特別に扱っていて、このシーケンスは一つの`&'の置き換えら れたが、文字列replacement中にある、`&'の前にない`\'は変更 されずにそのままにされた。これを表にすると以下のようになる。

この表はレキシカルレベルの処理で奇数個のバックスラッシュが実行時レベルで は偶数個になったものと、実行時にsubが処理した結果の両方がある(単 純のため、この後の表ではレキシカルレベルで偶数個の`\'がある場合だけ を例示する)。

伝統的アプローチに関する問題は、 `\'というリテラルにマッチしたテキストが続くというものを取得する 手段がない、ということである。

1992年のPOSIX標準はこの問題を解決した。この標準では、subgsub`\'の後の`\' にも `&'にも注目するということ を述べている。もし、`\'に続いて何かあれば、そのキャラクタはそのキ ャラクタそのものとして出力される。`\'`&'の解釈は以下のように なった。

これは問題を解決したかのように見える。しかし残念ながら、標準で述べている ことは一般的ではない。標準では、`\'はその直後にある`\'`&' 以外のすべてのキャラクタの特殊な意味を打ち消すと主張しているが、 その特殊な意味は定義されていない。これは二つの問題に繋がる。

  1. バックスラッシュは文字列replacement中では 二重に置かねばならず、伝統的なawkプログラムを破壊する。
  2. awkプログラムを確実に可搬性のあるものにするには、 文字列replacementにあるすべてのキャラクタ の前にバックスラッシュを置かなければならない。(12)

POSIXの標準は改定中である。(13) 上で述べた理由によって、よりオリジナルの結果に一致させるために標準の 改定が提案された。提案されたルールは`\'をマッチしたテキストの前 に置くのを可能にするために、特別なケースを持つ。

実行時レベルでは、現在三つの特殊なキャラクタ並び、`\\\&', `\\&', `\&'があるが、伝統的には一つしかない。しかし、伝統的なケースの ように、これら三つのシーケンスの一部ではない`\'は、そのまま出力に現 れる。

gawk 3.0 follows these proposed POSIX rules for sub and gsub. これら提案された規則が実際に標準に取り入れられるかどうかは現時点 ではわからない。これからのリリースのgawkでは、標準(それが 最終的な仕様であるかどうかに関らず)への追随をするだろう。この マニュアル も同様に更新されるだろう。

gensubのルールはかなり単純である。実行時レベルでは、gawk`\'を見つけると、その後ろに数字が続いている場合には、(その数字に対 応する)以前に現れているカッコで括られた部分正規表現にマッチしたテキスト が出力テキストに現れる。それ以外の場合、`\'の後ろのキャラクタはなん の意味もなく、そのキャラクタがそのまま出力テキストに現れるが、`\'は 出力されない。

レキシカルレベルの処理や実行時レベルの処理は複雑なので、subgsubには特殊ケースがある。あなたが置換を実行するときには、 gawkと、gensubの使用を勧める。

Built-in Functions for Input/Output

以下に挙げる関数は入出力(I/O)に関係するものである。 省略可能な引数はブラケット("[" と "]")で囲まれている。

close(filename)
入力や出力のためのファイルfilenameをクローズする。 この引数は出力のパイプへの、あるいはパイプからのリダイレクトの シェルコマンドであっても良い。この場合にはパイプがクローズされる。 詳しくは セクション Closing Input and Output Files and Pipesを参照。
fflush([filename])
filenameに結び付けられている オープンしたファイルの出力や、 パイプにリダイレクト出力しているシェルコマンド のための出力バッファをフラッシュする。 多くのユーティリティプログラムがその出力をバッファリングしている。 これは、ディスク上のファイルやターミナルに書き出す情報をメモリ上に貯えて おき、(送るのに)十分な量になったところで出力デバイスにまとめて送るもので ある。しかし、時としてバッファがいっぱいになっていなくても、情報をその出 力先に出力するために強制的にプログラムにそのバッファをフラッシュ (flush)させる必要があることがある。これが、fflushの目的である。 gawkもまたその出力をバッファリングしており、fflush関数は gawkのバッファを強制的にフラッシュさせるために使うことができる。 fflushは最近(1994年)にベル研究所で開発されたawkで 追加された。これはPOSIXの標準ではなく、`--posix'がコマンドラインで 指定された場合(セクション コマンドラインオプションを参照)は 使用できない。 gawkfflush関数を二つの方法で拡張した。一つは、引数なしの 場合を認めたというものであり、この場合は標準出力のバッファがフラッシュさ れる。もう一つは、引数として空文字列("") を認めたというもので あり、これはすべてのオープンされているファイル、パイプをフラッシ ュする。 fflushはバッファのフラッシュに成功した場合は0を返し、 それ以外では非0を返す。
system(command)
この関数は ユーザーがオペレーティングシステムのコマンドを実行し、 その後でawkプログラムに戻るということをできるようにする。 関数systemcommandで渡された文字列をコマンドとして 実行する。コマンドから戻ってきたとき、 実行したコマンドの終了ステータスを関数の値として返す。 例えば次のコード片をawkプログラムに埋めこむと、
END {
     system("date | mail -s 'awk run done' root")
}
システム管理者はこのawkプログラムが 入力を処理し終わって入力終了処理が始まったときに メイルを受け取ることになる。 パイプに対してprintprintfをリダイレクト することはほとんどの場合仕事を達成するのに十分である。 多くのコマンドを実行する必要があるのなら、シェルに対する パイプに対して単純に出力してやることで効率良く行うことが できるだろう:
while (more stuff to do)
    print command | "/bin/sh"
close("/bin/sh")
しかしながら、awkプログラムが対話的なものであったときには、 systemはシェルやエディタのような 大きなself-containedプログラムを用意するのに便利である。 一部のオペレーティングシステムではsystem関数を 実装することができない。サポートされていない場合にはsystemは 致命的エラーを引き起こす。

バッファリングというものは、あなたのプログラムが対話的(interactive) であろうがなかろうが、根の深い混乱を招く可能性がある。たとえば、 キーボードの前に坐っているユーザーとのやり取りを考えてみよう(14)

対話的なプログラムは一般的にはその出力は行バッファ、つまり 各行毎に出力を行うものとなっている。対話的でないプログラムは バッファがいっぱいになるまで実際に出力するのを待ち、複数行が バッファに溜まっているということもある。

以下に挙げるのはその違いを示す例である。

$ awk '{ print $1 + $2 }'
1 1
-| 2
2 3
-| 5
Control-d

各行は即座に出力されている。これを以下の例と比較してみよう。

$ awk '{ print $1 + $2 }' | cat
1 1
2 3
Control-d
-| 2
-| 5

ここでは、Control-dがタイプされるまで、何も出力されていない。 これはバッファリングされているためであり、それがcatに対する パイプへ(一度に)送られているからである。

Controlling Output Buffering with system

関数fflushはファイルやパイプに対する出力のバッファリングを 陽に制御する機能を提供する。しかしこれは、他のawk処理系では 使えないのでこれを使うと可搬性(portability)に欠けることになる。 出力バッファをフラッシュするための手段として、system関数を 空文字列を引数にして呼び出すというものがある。

system("")   # 出力をフラッシュする

gawkはこのようなsystem関数の使い方を特殊なものとして みなし、シェル(あるいは他のコマンドインタープリター)を何のコマンドも なしに起動するようなことはしない。このため、gawkでは この使い方は便利であるばかりでなく、効率も良い。 このやり方は他のawk処理系でも使えることが多いので、 必要ないシェルを起動してしまうことを避ける必要もない (他の処理系では、標準出力のバッファだけがフラッシュされ、その他の 出力バッファはフラッシュされないかもしれない)。

もし、プログラマーが期待することを考えているのなら、systemが すべてのペンディングされている出力をフラッシュするだろうことが 役に立つだろう。

BEGIN {
     print "first print"
     system("echo system echo")
     print "second print"
}

このプログラムは

first print
system echo
second print

上記のような出力をするはずで、下に示すようなものではない。

system echo
first print
second print

もしawksystemを実行する前にバッファをフラッシュしなければ、 後者のような(期待しない)出力がでてくることになる。

Functions for Dealing with Time Stamps

awkプログラムの common useは、特定のレコードが記録された 時刻を示すタイムスタンプ情報からなるログファイルに対する処理である。 多くのプログラムは、タイムスタンプをtimeというシステムコール が返すある特定の時点からの経過秒数の形で記録する。 POSIX システム上では、これは UTCの1970年1月1日の午前零時からの 経過秒数である。

このようなログファイルの処理をより簡単にして便利なレポートを 生成するために、gawkにはタイムスタンプに関連する働きをする 二つの関数がある。これらの関数は両方ともgawkでの拡張であり、 POSIXの標準にもgawk以外のawk処理系にもない。

省略可能なパラメーターは、角カッコ("[" と "]")で囲まれている。

systime()
この関数はシステムが始まった時点から現在までの時間を秒で返す。 POSIX のシ ステムでは、これはUTCでの1970年1月1日の0時を起点としている。 これは他のシステムでは違った数字かもしれない。
strftime([format [, timestamp]])
この関数は文字列を返す。この関数は ANSI のC標準ライブラリの同名の関数と同じ ものである。timestampで特定される時間を文字列にするのに使い、文字列 formatをベースに文字列化する。 timestampsystimeが返した値と同じ書式である。 引数timestampが省略された場合、gawkは タイムスタンプとして現在時刻を使用する。 引数formatが省略された場合、 code{strftime}は"%a %b %d %H:%M:%S %Z %Y"を 使用する。この書式文字列は dateユーティリティの出力と(ほぼ)同じ出力を生成する (3.0以前のバージョンのgawkは引数formatを省略することは できなかった)。

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

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

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

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

変換指定文字が上に挙げたものに含まれていない場合には、その結果は未定義で ある。(16)

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

gawkのための パブリックドメインバージョンの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となる)。
%G
ISO week numberでの年の十進表記 例えば、1993年の一月一日は1992年の53週である。 したがって、これに対するISO week numberは 1993年であるにもかかわらず1992である。 同様に、1973年の12月31日は、それが1973年であるにもかかわらず ISO week numberでは1974年の第一週となる
%g
ISO week numberでの年の世紀の部分を除いた(下二桁ということ)ものの 十進表記(00から99)。
%Ec %EC %Ex %Ey %EY %Od %Oe %OH %OI
%Om %OM %OS %Ou %OU %OV %Ow %OW %Oy
これらは"代替表現"(alternate representations)であり、 二番目の文字((`%c'`%C'など)だけが指定に使われる。 これらは認識されるが、それらの通常の意味が使用される。 (17)。 (これらはPOSIXのdateユーティリティに従うことを容易にする。)
%v
VMSフォーマットでの日付(例 20-JUN-1991)。
%z
+HHMM という書式のタイムゾーンオフセット (この書式はRFC-822/RFC-1036 日付ヘッダを生成する必要がある)

次に挙げるサンプルは、awkによるPOSIXのdateユーティリティの 実現である。通常は、dateユーティリティは、現在の日付と時刻をよく 知られた書式で出力する。しかし、`+'で始まる引数を与えた場合、 dateはその引数の非書式指定部分はそのまま標準出力にコピーし、現在 時刻にしたがって、文字列中の書式指定子を解釈する。例を挙げよう。

$ date '+Today is %A, %B %d, %Y.'
-| Today is Thursday, July 11, 1991.

以下のプログラムはgawkバージョンのdate ユーティリティである。 タイムゾーンがUTCにセットされたかのようにdateを実行させる `-u'オプションを取り扱うために、 シェルラッパー(shell wrapper)がある。

#! /bin/sh
#
# date -- approximate the P1003.2 'date' command

case $1 in
-u)  TZ=GMT0     # UTCを使う
     export TZ
     shift ;;
esac

gawk 'BEGIN  {
    format = "%a %b %d %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
}' "$@"

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