あなたは、変数をどのように追加するには
The GNU Awk User's Guide
もっともよく行われるアクションの一つは、入力の一部もしくは全部を出力するこ とである。単純な出力のためにprint
文を使い、整形して出力するために printf
文を使う。この両者はこの章で説明する。
print
文は出力を単純に、標準的な書式で行う。カンマで区切られたリストに なっているデータを文字列とするか数値として出力するかを特定できるだけである。 出力は一つのスペースで区切られ、最後に改行が加えられる。例を挙げよう。
print item1, item2, ...
アイテムのリストは、全体を括弧でくくる事もできる。この括弧は、アイテムのいず れかが関係演算子を使った式である場合には使う必要がある。そうしないと、リダ イレクションと混同してしまう可能性があるだろう (セクション Redirecting Output of print
and printf
を参照).
プリントの対象となるアイテムは文字列定数や数値定数、カレントレコードのフィー ルド($1
のような)、変数、式である。 print
文は出力する値を完全 に計算する。二つの例外として、どのように出力するか、つまりどの位カラムを出力 するか、指数表示を使うか使わないか等を指定することはできない
print
文は演算結果を出力するのに汎用的なものである。しかしながら、 二つの例外があって、どのように出力するのか、つまりどのくらいのカ ラム数で、とか指数表記を使うのか使わないのかなどということを指定できない (この例外についてはセクション Output Separatorsを参照, および セクション Controlling Numeric Output with print
を参照.)。 このためにはprintf
文を使う必要がある (セクション Using printf
Statements for Fancier Printingを参照)。
単に`print' とだけ書かれて何もアイテムのない`print' 文は `print $0'と同じ動作、つまりカレントレコード全体を出力する。空行を出力 するには、`print ""'として、空文字列を指定する。
固定したテキストを出力するためには、"Hello there"
の様な文字列定数 を使う。ここで二重引用符を忘れた場合、そのテキストは式として扱われて、おそ らくはエラーとなるだろう。また、二つのアイテムの間にはスペースが出力される ことを覚えておいて欲しい。
ほとんどの場合、各々のprint
文は一行の出力を作り出す。しかし、一行にか ぎらない。もし、アイテムの値が改行を含む文字列であった場合、改行は残りの文字 列とともに出力される。このやり方で、一つのprint
で多くの行を出力するこ とができる。
次に挙げるのは改行が埋め込まれた文字列の出力の例である (`\n'はエスケープシーケンスであり、改行を表わすものである セクション エスケープシーケンスを参照)。
$ awk 'BEGIN { print "line one\nline two\nline three" }' -| line one -| line two -| line three
次の例はカレントレコードの最初の二つのフィールドを空白で区切って出力する。
$ awk '{ print $1, $2 }' inventory-shipped -| Jan 13 -| Feb 15 -| Mar 15 ...
print
文を使うときにありがちな間違いは、二つのアイテムの間に置かれるカ ンマを忘れてしまうという事である。それはスペースなしに、一つにまとまって出力 される結果となるだろう。なぜなら、二つの並んだ文字列というのはawk
で は連接を行う式を意味するからだ。カンマがない例として、
$ awk '{ print $1 $2 }' inventory-shipped -| Jan13 -| Feb15 -| Mar15 ...
`inventory-shipped'にあまり馴染みのない人に対してもわかりやすい出力 をしよう。最初のヘッダ行で何を出力しているかを明確にしようとして、月ごと の量($1
)と、緑のクレーの積込量($2
)のテーブルにヘッダを付け 加えている。これをBEGIN
パターン (セクション 特殊パターンBEGIN
とEND
を参照) を使って出力の最初に一回だけ出力させている。
awk 'BEGIN { print "Month Crates" print "----- ------" } { print $1, $2 }' inventory-shipped
どう出力されるか予想できるだろうか? このプログラムの出力はこうなる。
Month Crates ----- ------ Jan 13 Feb 15 Mar 15 ...
ヘッダとデータのテーブルがきちんと揃っていない! しかし、二つのフィールドの 間に固定長のスペースを出力するようにできる。
awk 'BEGIN { print "Month Crates" print "----- ------" } { print $1, " ", $2 }' inventory-shipped
このカラムの揃え方は多くのカラムがあった場合に揃えるのが少々面倒になることが 想像できるだろう。二、三個のカラムのためなら単純にスペースを数えられるだろう が、これがもっと多かったりすると数え間違えやすくなる。それが printf
文が作られた理由である (セクション Using printf
Statements for Fancier Printingを参照)。 その機能の一つにデータのカラムをそろえることがある。
print
文やprintf
文では、任意のカンマの後に 改行を置くだけで行の継続を行うことができる。 (セクション awk
の文と行を参照).
先に述べたように、print
文はカンマで区切られたアイテムのリストを含 む。出力では、各アイテムは単一のスペースで区切られる。これはただのデフォ ルトであり、常にそうであるわけではない。組込み変数のOFS
に任意の文 字列をセットすることによって出力フィールドセパレータを指定すること ができる。この変数の初期値は" "
であり、単一のスペースである。
print
文による出力全体は出力レコードと呼ばれる。各print
文は一つのレコードを出力し、その後に出力レコードセパレータと呼ばれ る文字列を出力する。組込み変数ORS
がこの文字列を特定する。ORS
の初期値は"\n"
という文字列である。これは改行であり、したがって、通 常は各print
文は分割された行を作成する。
OFS
やORS
といった変数に新しい値をセットすることによって、 出力フィールドや出力レコードをどのように分割するかを変更することが できる。通常これを行う場所は、入力がまだ処理されないBEGIN
ルール (セクション 特殊パターンBEGIN
とEND
を参照) の中である。同じことを、コマンドライン上で入力ファイル名の前に変数への 代入を行うことでもできるし、`-v'オプションを使うことでもできる。 (セクション コマンドラインオプションを参照).
次の例では、各入力レコード中のセミコロンで区切られた フィールドの一番目と二番目を、各行の後ろに空行を追加して出力する。
$ awk 'BEGIN { OFS = ";"; ORS = "\n\n" } > { print $1, $2 }' BBS-list -| aardvark;555-5553 -| -| alpo-net;555-3412 -| -| barfly;555-7685 ...
ORS
が改行を含んでいなければ、すべての出力は 陽に改行を出力しない限りは一行にまとまって出力されることになる。
print
文を数値を出力するために使った場合、awk
は内部で数値を (その数値を表す)文字列に変換し、その文字列を出力する。 awk
はこの変 換動作のためにsprintf
関数を使用する。(セクション Built-in Functions for String Manipulationを参照).現在のところ、sprintf
関数が数値(や文字列)をどのように書式化するかを記述されている format specificationを受諾し、数値の書式指定は違った方法が何種類もあるということ だけで十分である。書式の違いは セクション 書式制御文字を参照.で詳しく述べられている。
組込み変数のOFMT
は、出力をおこなうときにprint
がsprintf
を使って数値を文字列に変換するための書式のデフォルト設定を保持している。 OFMT
のデフォルトの値は"%.6g"
である。OFMT
の値を違ったも のにすることによって、print
が数値をどのように出力するかを変更するこ とができる。簡単な例を挙げよう。
$ awk 'BEGIN { > OFMT = "%.0f" # 数値を整数として(丸めて)出力する > print 17.23 }' -| 17
POSIX標準に従えば、OFMT
に浮動小数点の変換指定ではない なにかをセットした場合のawk
の動作は定義されてない(d.c.)。
あなたがprint
で出力するには複雑な書式を使いたいのであれば、printf
を使うと良い。 printf
を使うことによってアイテムごとにその幅を指定し たり、数値を出力するのにそれをどのようなスタイルで出力するのかを指定するこ とができるようになる(使用する基数や、符号を出力するかどうか、小数点以下何 桁まで出力するか)。あなたは他の引数をどのように、どこに出力するかを制御する format stringと呼ばれる文字列によって、それを行なうことが可能である。
Introduction to the printf
Statement
printf
文は次のような形式である。
printf format, item1, item2, ...
引数リスト全体をカッコで括ることもできる。このカッコはリストのいずれかの アイテムが関係演算子`>'を使った式であるときには必要となる。 カッコがないと、その文はリダイレクトと混同される可能性がある。 (セクション Redirecting Output of print
and printf
を参照).
printf
とprint
の違いは引数formatにある。 これは文字列として扱われる式で、他の引数をそれぞれどのように 出力するかを指定する。これは書式文字列(format string)と 呼ばれる。
この書式文字列は ANSI Cライブラリのprintf
関数のものと同じである。大 部分の書式は(書式文字列の)文字通りに出力されるテキストである。書式指定子 はアイテム一つ毎に一つの割りあいで、このテキスト中に置かれている。個々の書 式指定子は、次のアイテムをどのような書式で出力するかを指定している。
printf
文は改行を自動的に付加することはせず、書式文字列で 指定されたものだけを出力する。 したがって、改行が必要ならば、書式文字列にそれを含めなければならない。 OFS
やORS
といった変数にある出力セパレータは printf
に対して何の影響も与えない。例えば、
BEGIN { ORS = "\nOUCH!\n"; OFS = "!" msg = "Don't Panic!"; printf "%s\n", msg }
これは`Don't Panic!'というメッセージを出力する。
書式制御文字
書式指定子は`%' で始まり、(printf文でどのように出力するかを指定する) 書 式指定文字で終わる(`%'そのものを出力したい場合には `%%'と記述する)。 書式指定文字は値をどのように出力するかを指定する。書式指定子の残りは、どの位 のフィールド幅で出力するかというような事を指定する(省略可能な)修飾子である。
以下に書式指定文字の一覧を挙げる。
c
- 数値をASCIIキャラクタとみなして出力する。`printf "%c",65'は `A'を 出力する。文字列を与えた場合は文字列の先頭にあるキャラクタを出力する。
d
i
- どちらも同じで、十進整数を出力する。 `%i'はANSI Cとの互換性のための仕様である。
e
E
- これは数値を科学(または指数)形式で出力する。 例えば、
printf "%4.3e\n", 1950
これは小数点以下を含めて全部で四つの数字からなる `1.950e+03'を出力する。 `4.3' は 修飾子(modifiers)であり、詳しくは後述する。 `%E'は`e'の代わりに`E'を出力するものである。 f
- 浮動小数点形式で数値を出力する。例えば、
printf "%4.3f", 1950
これは小数点以下三桁を伴った四桁のsignificant figuresである `1950.000'を出力する。 `4.3' は 修飾子(modifiers)であり、詳しくは後述する。 g
G
- 科学表記か浮動小数点表記の、いずれか出力するキャラクタ数が少なくなる 方で出力する。結果が科学表記であったとき、 `%G' は `E' を `e'の代わりに使用する。
o
- 無符号の発進整数を出力する(八進数、もしくは八進表記は数字として`0' から `7'を使用する。十進数の8は八進数では`10'と表記される)
s
- 文字列を出力する
x
X
- 16進の符号なし整数を出力する(十六進もしくは十六進表記では、数字は`0' から`9'までと`a'から`f'である。十六進数字の`f'は十進 数の15を表わす)。`%X'は`a'から`f'ではなく、`A' から `F'の文字を使用する。
%
- これは本当は書式制御文字ではない、しかし`%'の後に続けて書かれた場合 には意味がある。`%%'と並べて書いたときには一文字の`%'を出力し、 引数を取らない。また、すべての修飾子を無視する。
整数指定の書式指定子を、C言語のlong
で表わせる範囲外の 値に対して使ったとき、gawk
は書式指定子を `%g'に切り替える。他のawk
処理系では 不正な値を出力するか、完全に違うことをする。 (d.c.)
printf
の書式の修飾子
書式指定には出力されるアイテムの値と、出力する大きさを制御するために 修飾子を含めることができる。修飾子は`%'と書式指定文字の間に置か れる。後で挙げる例では、出力中の空白を"*" というシンボルで表わし ている。以下は使用することのできる修飾子である。
Visual Basicを使用して現在の日付と時刻を表示する方法-
- マイナス記号は出力幅の修飾に使い、与えられた出力幅の中で左詰めを行うことを 指示する。通常は与えられた出力幅の中で右詰めで表示がなされる。 従って、次のような指定をすると、
printf "%-4s", "foo"
`foo*'が出力される。 space
- 数値の変換の際に、その値が正であればスペースを、負であればマイナス記号を 数値の前に置く。
+
- プラス記号は幅指定の修飾子(後述する)の前で使用し、変換された数値が正の数 値であっても、その前に必ず符号をつけることを指示する。`+'はスペース 修飾子をオーバーライドする。
#
- `%o'の前に置いた場合、数値の前にゼロを置く。 `%x'や`%X'の前に置いた場合、出力する数値が0でなかったときに それに先行して`0x' や `0X'を置く。 `%e', `%E', `%f' の場合、常に小数点をつけるようにする。 `%g', `%G'の場合、小数点以下の0も省略されないようにする。
0
- %に続いた`0'はフラグとして動作し、出力のパディングを、スペースでは なく0で行うようにする。これは数値ではない出力書式のときも適用される(d. c.) このフラグはフィールド幅が実際に出力される値の幅よりも大きい場合にの み効果を持つ。
width
- これはフィールドの幅を指定する数字である。 `%' と書式指定文字の間に置 かれ、この幅にフィールドを広げて出力を行うことを指定する。デフォルトではフィ ールドを埋めるためのスペースはフィールドの左から置かれる。 次のように指定した場合、
printf "%4s", "foo"
`*foo'を出力する。 width は(出力の)最小幅であって、最大幅ではない。アイテムの値が width よりも多くのキャラクタを必要としたならば、出力はその幅となる。 したがって、printf "%4s", "foobar"
これは`foobar'を出力する。 マイナス記号を伴ったフィールド幅指定は、幅あわせのためのスペースを フィールドの左ではなく右に置く。 .prec
- これは出力のときを精度を指定するのに使用する数字である。 書式指定が`e', `E', `f' の場合には、 この数字は小数点以下何桁まで出力したいかをしめす数字である。 書式指定が`g', `G' の場合、 有効数字の最大桁数を示す数字である。 `d', `o', `i', `u', `x', `X' といった書式指定の場合、出力する数値の最少桁数である。 文字列にたいしては、出力する文字列の最大文字数を指定する 数字となる。したがって、
printf "%.4s", "foobar"
この例の出力は `foob'となる。
Cライブラリのprintf
は実行時にwidthとprecを指定すること (例えば"%*.*s"
のように)ができる。書式文字列中でwidth や precを記述する代わりに、引数リストでそれを渡す事ができる。例えば
w = 5 p = 3 s = "abcdefg" printf "%*.*s\n", w, p, s
これは次の書き方と等しい。
s = "abcdefg" printf "%5.3s\n", s
上のプログラムは両方とも`<**abc>'を出力する。
awk
の初期のバージョンではこの機能がサポートされていなかった。次の様 に書式文字列を組み立てるのに文字列連接を使う事で、この機能をシミュレートす る事が可能である。
w = 5 p = 3 s = "abcdefg" printf "%" w "." p "s\n", s
これは読み易いとは云えないが、きちんと働く。
Cプログラマはprintf
の書式指定文字列中で`l'とsamp{h}というフ ラグを使っているかもしれない。これらはawk
では不正なフラグである。 大部分のawk
処理系ではこれらを何の警告もなしに無視する。 `--lint'がコマンドラインで指定されている場合 (セクション コマンドラインオプションを参照)、gawk
はこれらのフラグを 使用したときに警告を発する。同様に`--posix'が指定されている場合には 致命的エラーとなる。
printf
を使った例
次の例は、printf
を整列したテーブルの出力に どのように使用するかというものである。
awk '{ printf "%-10s %s\n", $1, $2 }' BBS-list
このプログラムは `BBS-list'というファイル中のBBSの名前($1
) を10文字の文字列として、左寄せで出力する。同様に 電話番号($2
)をそれに続いて出力する。 結果として、二つのカラムからなる、名前と電話番号の きちんと並んだテーブルが作成される。
$ awk '{ printf "%-10s %s\n", $1, $2 }' BBS-list -| aardvark 555-5553 -| alpo-net 555-3412 -| barfly 555-7685 -| bites 555-1675 -| camelot 555-0542 -| core 555-2912 -| fooey 555-1234 -| foot 555-6699 -| macfoo 555-6480 -| sdace 555-3430 -| sabafoo 555-2127
なぜ電話番号を数値として出力するように指定していないのかわかるだろうか? ここ では数字がダッシュで区切られているので文字列として出力している。もし、これを 数値として出力しようとしたならば、そこで得られるものは最初の三つの数字 `555'である、これは混乱を招くだろう。
ここでは電話番号の出力時の幅を指定していない。それは 出力行の最後にあるものであり、その後ろにスペースを置く必要が ないからだ。
先頭のカラムにヘッダを付け加えることによってテーブルをより見やすいものに している。これを行う為に、BEGIN
パターン (セクション 特殊パターンBEGIN
とEND
を参照) を使ってヘッダをawk
プログラムの始めで一度だけ出力している。
awk 'BEGIN { print "Name Number" print "---- ------" } { printf "%-10s %s\n", $1, $2 }' BBS-list
この例ではprint
文と printf
文を混ぜて使っているのに 気がついただろうか?、同じ結果をprintf
文だけを使って得る事ができる。
awk 'BEGIN { printf "%-10s %s\n", "Name", "Number" printf "%-10s %s\n", "----", "------" } { printf "%-10s %s\n", $1, $2 }' BBS-list
ヘッダと同じ書式指定を使って各カラムを出力しているので、ヘッダと 同じように桁揃えされる。
三回同じ書式を指定するのに、変数に書式を代入してその変数で指定する方法が ある。実例を挙げよう。
awk 'BEGIN { format = "%-10s %s\n" printf format, "Name", "Number" printf format, "----", "------" } { printf format, $1, $2 }' BBS-list
試しに以前に説明した (セクション The print
Statementを参照). `inventory-shipped'の例の、表題と表のデータを printf
文でそろえてみてほしい。
これまでは出力は標準出力に対してのみ行われていた。 print
と printf
の両方とも別の場所に出力を送ることができる。 これはリダイレクトと呼ばれる。
リダイレクションはprint
文か printf
文の後に書く事ができる。 awk
におけるリダイレクションはシェルコマンドのリダイレクションとよく似 ているが、awk
ではプログラムの中にリダイレクションの指示を書くという点 が違っている。
以下に、三種類の出力リダイレクションの例、 出力をファイルに送ったり、ファイルに追加したり、パイプを通して 他のコマンドに出力したりするものを挙げる。 これらの例ではprint
文が使わ れているが、printf
文を使っても同じように動作する。
print items > output-file
- この書式のリダイレクションではアイテムの出力をoutput-fileという ファイルに対して行う。ファイル名output-fileは式であってもかまわない。 式を文字列に変換し、その後にファイル名として使用する (セクション 式を参照)。 この書式のリダイレクションは最初の出力を行う前に、output-file 、ファイ ルの削除を実行する。以後はoutput-file の削除はしないでファイルに追加す る形で出力を行う。もしoutput-file が存在しなければファイルが新たに作成 される。 たとえば、次に挙げるプログラムはBBSの名前のリストを`name-list'という名 前のファイルに、電話番号のリストを`phone-list'というファイルにそれぞれ 出力する。出力されたファイルの各行は、一つの名前あるいは番号で構成される。
$ awk '{ print $2 > "phone-list" > print $1 > "name-list" }' BBS-list $ cat phone-list -| 555-5553 -| 555-3412 ... $ cat name-list -| aardvark -| alpo-net ...
print items >> output-file
- このリダイレクションは、出力をoutput-fileというファイルに対して行う。 先ほどの`>'での指定と違うのは、output-fileの削除が行われないとい うことである。出力はファイルに追加される形で行われる。 もしoutput-fileが存在していなければ、作成される。
print items | command
- こうすることによって出力を、ファイルに対して行う代わりにpipeを通して渡 す事ができる。このやり方のリダイレクションは commandへのパイプをオープ ンし、そのパイプを通して、 commandを実行する為に作られたプロセスへ itemsの値を出力する。 リダイレクションの引数commandは
awk
の式でも良い。 その式の値はコマンドを実行するための文字列に変換される。 次の例では二つのファイルが作られる。一つはソートされていないBBSの名前のリスト。 もう一つはアルファベットの降順にソートされたリストである。awk '{ print $1 > "names.unsorted" command = "sort -r > names.sorted" print $1 | command }' BBS-list
この例のソートされていないリストは、ソート済みリストがパイプを通ってsort
ユーティリティが出力する間に、通常のリダイレクトで書き込まれる。 次の例はリダイレクトを使って、メイリングリスト`bug-system'に従ってメイ ルを送るものである。これはトラブルにあったときに、システムメンテナンスの為に 定期的にawk
スクリプトを実行するような場合に便利だろう。report = "mail bug-system" print "Awk script failed:", $0 | report m = ("at record number " FNR " of " FILENAME) print m | report close(report)
メッセージは文字列連接と変数m
に保持されている内容を 使って組み立てられている。作成されたメッセージはパイプラインを 通してmail
プログラムに送られる。 ここでclose
関数を呼んでいるのは、パイプを閉じてすぐに出力を送る ためである。 セクション Closing Input and Output Files and Pipesを参照, により詳しく記述されている。この例はファイル、コマンドを与えるのに変数を 使っている。つまり常に文字列定数を使う、というわけではないということで ある。awk
が毎回文字列値を要求するので、変数を使うというのは一 般にはいいアイデアである。
`>', `>>', `|' を使って出力をリダイレクトするときに、file や commandがそれまでにプログラム中で使っていなかったり出力する直前にク ローズを行っていたりすると、ファイルやパイプをオープンするためにシステムに問 い合わせを行う。
多くのawk
処理系では、awk
プログラムが オープンできるパイプラインの数はたった一つである! gawk
ではこのような制限はなく、使用しているオペレーティングシステム が許すだけパイプラインをオープンすることができる。
実行中のプログラムは、慣習的に三つの入出力ストリームを何もしなくても読み込み、 書き込みのために使えるようになっている。それらは標準入力, 標準出 力, 標準エラー出力として知られている。これらのストリームはデフォルト でターミナルの入出力に割り当てられている。しかし、しばしばシェルでのリダイレ クトによって(`<', `<<',`>', `>>', `>&' `|'と いったオペレータを使って)、変更される。標準エラー出力はエラーメッセージの出 力にだけ使われる。それは、標準出力、標準エラー出力の二つのストリームがあり、 別々にリダイレクトを行う事が可能であるからである。
他のawk
処理系では、次のような方法でしか awk
プログラ ムから標準エラー出力にエラーメッセージを出力する事ができない。
print "Serious error detected!" | "cat 1>&2"
これは標準エラー出力にアクセスするためにパイプを開いてawk
プロセスの出 力を渡している。これはエレガントとは言い難いし、他のプロセスを必要とする非効 率的なやり方である。多くの人はこの点にあまり気を使っていないようなawk
プログラムを書いている。こういったやり方に代えて、エラーメッセージを次のよう にしてターミナルに送る。
print "Serious error detected!" > "/dev/tty"
これは多くの場合同じ結果となるだろうが、常に、ではない。標準エラー出力は通常 ターミナルであるが、リダイレクトすることができ、その場合には出力はターミナル に対しては行われない。事実、awk
をバックグラウンドジョブで実行すると、 そのプロセスはターミナルを持っておらず、`/dev/tty'のオープンは失敗する。
gawk
は三つの標準ストリームにアクセスするために特殊なファイル名を持っ ている。gawk
で入出力をリダイレクトするときにリダイレクト先のファイル 名が次の特殊な名前の中にあれば、gawk
は直接(定義されている)ストリー ムを使用する。
- `/dev/stdin'
- The standard input (file descriptor 0). 標準入力(ファイルディスクリプタ0)。
- `/dev/stdout'
- 標準出力(ファイルディスクリプタ1)。
- `/dev/stderr'
- 標準エラー出力(ファイルディスクリプタ2)。
- `/dev/fd/N'
- ファイルディスクリプタnでアクセスされるファイル。このファイルは
awk
を実行しているプログラムによって(典型的なのはシェル)、オープンされていなけ ればならない。特別な操作をしない限り、ディスクリプタの0,1,2だけが使用可能で ある。
`/dev/stdin', `/dev/stdout', `/dev/stderr'等のファイル名は それぞれ`/dev/fd/0',
`/dev/fd/1', `/dev/fd/2'の 別名になっている。
gawk
プログラムでエラーメッセージを出力する適当な手段は次の様に `/dev/stderr'を利用することである。
print "Serious error detected!" > "/dev/stderr"
gawk
はgawk
が実行されているプロセスの情報にアクセスするために特 殊なファイル名を与えられている。これらの"ファイル"はそれぞれ、ひとつの情報 のレコードを表わしている。これらのファイルを二度以上読み込むためには、 最初にclose
をつかってクローズしなければならない。 (セクション Closing Input and Output Files and Pipesを参照). ファイルの名前は
- `/dev/pid'
- このファイルを読むと、カレントプロセスのプロセスIDが 十進数で、改行で終端されて返ってくる。
- `/dev/ppid'
- このファイルを読むと、カレントプロセスの親プロセスIDが 十進数で、改行で終端されて返ってくる。
- `/dev/pgrpid'
- このファイルを読むと、カレントプロセスのプロセスグループIDが 十進数で、改行で終端されて返ってくる。
- `/dev/user'
- このファイルを読むと、改行で終端されスペースで区切られたフィールドを持つ 一つのレコードが返ってくる。そのフィールドは以下のような情報を表している ものである。
$1
-
getuid
システムコールの返す値(実ユーザーID番号)。 $2
-
geteuid
システムコールの返す値(実効ユーザーID番号)。 $3
-
getgid
システムコールの返す値(実グループID番号)。 $4
-
getgid
システムコールの返す値(実効グループID番号)。
getgroups
システムコールが返した グループIDである(Multiple グループはすべてのシステムでサポートされている わけではない)。
これらの特殊ファイルはコマンドライン上でデータファイルのように使ってもよ いし、awk
プログラムの中で入出力のリダイレクトで使ってもよい。ただ し、`-f'オプションを伴ったソースファイルとしては使うことはできない。
gawK
が互換モード(セクション コマンドラインオプションを参照) で動作しているときには、これらの特殊ファイルの認識は禁止される。
警告: あなたの使うシステムが`/dev/fd'というディレクトリ (あるいは先に述べたような特殊ファイル)を持っていないのであれば、これらのファ イル名をgawk
それ自身が解釈する。例えば、 `/dev/fd/4'を使ってファ イルディスクリプタの4 番に出力しようとすると、ファイルディスクリプタの4番が dup
され、その結果の新しいファイルディスクリプタに出力が行なわれる。こ のことはほとんどの場合重要なことではないが、重要なのはファイルディスクリプタ の0、1、2番に関係するファイルをクローズしないということである。もし、これら のうちどれかをクローズしてしまったならば、その結果は予測できないものとなる。
プロセスに関連した情報を提供する特殊ファイルは、将来のバージョンのgawk
ではなくなる可能性がある。 セクション 将来予定されている拡張を参照.
もし同じファイル名や同じシェルコマンドが、awk
プログラムの実行中に二度 以上getline
(セクション getline
を使った入力を参照) と一緒に使われた場合、ファイルのオープンやコマンドの実行は 最初の一回だけ行われる。つまり最初にファイルやコマンドからレコードを読み込む ときである。次にgetline
を使って読むときは同一のファイル、コマンドから 別のレコードを読み込む。
同様にファイルやパイプが出力のためにオープンされたとき、 awk
は(オープンした情報を)そのファイル名やコマンド名と結び付け、 後になって出力したときにその出力をそれまでのものに追加する形で行う。 ファイルやパイプはawk
が終了するまでオープンされている。
このことによって、同じファイルを再び最初から読み始めたいときや、シェルコマン ドを再実行(コマンドの出力からもっと読みだしたいとき)したいようなときには特 別な手順を踏まねばならない。つまり、次の例のようにclose
関数を使わなけ ればならない。
close(filename)
or
close(command)
引数filenameやcommandは任意の式であってよい。その値は、ファ イルをオープンしたりコマンドを起動した文字列と(スペースや他の"irrelevant" (無関係)なキャラクタも含めて) 正確にマッチしなければならない。例え ば、次のようにパイプをオープンしたら、
"sort -r names" | getline foo
次のようにクローズしなければならない。
close("sort -r names")
一度この関数呼びだしが実行されると、次のファイルやコマンドからの@code {getline}や、ファイルやコマンドに対するprint
、printf
は、フ ァイルの再オープンやコマンドの再実行を行う。
ファイルやパイプをクローズするときの式は、それらをオープンしたり、コマ ンドを起動したときの文字列とまったく同じものでなければならない。これファ イル名やコマンドを格納するために変数を使ってみるのにいい題材である。例え ば、パイプを次のようにしてオープンしたならば、
先程の例はこのように書くことができる。
sortcom = "sort -r names" sortcom | getline foo ... close(sortcom)
これは、awk
プログラムに見つけづらい打ち間違いのエラー (typographical errors)が入り込むのを防ぐのに役立つ。
以下に出力ファイルをクローズする必要があるかもしれない理由を幾つか挙げる。
- 同一の
awk
プログラム中で、書き込みを行ったファイルを後で読み返すため。 最後の出力が終わったときにファイルをクローズした後で、getline
を使って そのファイルから入力を始める事ができる - 同一の
awk
プログラム中で、連続的に複数のファイルに書き込みを行うため。も しファイルのクローズを行わないでいると、一つのプロセスでオープンできるシステ ムの限界数を越えてしまうかもしれない。それを避けるために書き込みが終了したとき にそれをクローズする。 - コマンドを終了させるため。パイプを通して出力をリダイレクトしているとき、パイ プから読み込みを行っているコマンドはパイプがオープンされていると通常通り入力 を読み込もうとしつづける。多くの場合、コマンドはパイプがクローズされるまでそ の実行を停止できない。例えばリダイレクトで
mail
プログラムに出力を送る と、そのメッセージはパイプがクローズされるまで実際には送られない。 - 同じプログラムを、同じ引数で再度実行させるため。これは最初に実行したときに続 いて入力を与えるということではない。 例えば、パイプの出力を
mail
プログラムに送ることを考えてみよう。クロー ズしないでこのパイプに数行の出力をリダイレクトすると、一つのメッセージに数行 があるという結果となるだろう。対照的に、各行を出力した後にパイプをクローズす ると、それぞれの行は別々のメッセージに分割される。
close
はクローズに成功した時0を返し、失敗したときに0以外を返す。 失敗した場合には変数ERRNO
にエラーの発生を示す文字列がセットされる。
システムがオープンすることを許している以上の数のファイルを使おうした場合、 gawk
は使っているデータファイルの中で多重オープンを 試みる。 gawk
のこれをおこなう能力はあなたが使っているオペレーティングシステ ムの能力に依存する。したがって、ファイルを使いおわったら常にclose
するということがよいやり方であるし、移植性のためによいのである。
0 コメント:
コメントを投稿