講座「文系のためのawkプログラミング入門」
すでにawkの組込み変数についていくつか見てきました。$1,$2,... などを使うことによって、効率よくスクリプトが書けることを理解されたと思います。スクリプトの中で、組込み変数を用いる意義を確認しておきましょう。たとえば、次のようなスクリプトを考えてみましょう。
{ print $1 }
このスクリプトは、入力レコードの、第1フィールドを、$1という変数を用いて表すことによって、この処理を、全ての、それぞれ異なった入力行に対して行うことを可能にしています。
生のデータの代わりに、それを格納する変数を用いることによって、ある処理を一般的に記述することが可能になります。実際には様々に異なるデータに対して、ある共通の処理を行うことが可能になるわけです。このようなことは、変数を使うことなしには不可能です。プログラミングは、結局、あるデータ処理の過程を、一般的に定義し記述することに他なりませんが、それには変数の使用が不可欠です。従って、通常、プログラミング言語は独自の変数の使用法をもっています。awkもまた、$1,$2,...などのような組込み変数だけでなく、プログラマが自分で変数を作り、それを用いることができるような仕組みをもっています。そのことによって、さらに柔軟にテキスト処理を行えるようになります。今回はスクリプトのなかで、プログラマが自分で変数を作成し用いる方法について学びます。
組込み変数で学んだように、プログラマが独自に作る変数も、数値や文字列を格納する容器、入れものです。そして、入れものである変数は名前で区別されます。最初に覚えるべきことは、変数の名前のつけ方です。awkで、ユーザが作ることの出来る変数の命名規則は以下のようなものです。
1) 最初は英字かアンダーバー、すなわち下線 "_" ではじまる。
2) 2字以降は英字または数字とアンダーバー("_") が0個以上続く。
3) 英字の大文字と小文字は区別される。
4) awkですでに独自の意味で使われている語(予約語という)は使えない。
正しい変数名は次のようなものです。
x, y, x1,y2,file_name,_pos,....
変数名と見なされないものの例は次のようなものです
1x, 2y …(変数名とは認められない) 数字で始めることは出来ない。
file-name …(変数名とは認められない) 変数では使えない文字がある
print …(変数名とは認められない)awk自身の予約語である
BEGIN …(変数名とは認められない) 同上
又 x と X 、 Name と name は別の変数と見なされます(プログラミング言語の中には、変数の大文字小文字を同一視するものもありますが、awkは区別します。変数をスクリプト中で使うときは、この点に要注意です)。
awkで変数を作るのには、なにも特殊な手続きはいりません。ただスクリプト中に書けばよいだけです。書くことによって、変数は存在し始めます。そして変数は、数値や文字列の入れもの、容器です。そこに数値や文字列を入れることを「代入」といいます。この代入の方法を知っている必要があります。これも簡単です。代入は = を使って行います。 = の左辺に変数を、右辺に代入する値を書くだけです。
# script4-1 BEGIN{ x = 2 # x は 2 という数値をもつようになる y = "abc" # y は "abc" という文字列値をもつようになる print x print y }
上のように、文字列はダブルクォーテイションで囲むことを忘れないようにしなければなりません。上のスクリプトでは、二つの変数にそれぞれ、数と文字列が代入されています。
2 "abc"
上のような状態になっているわけです。そして、上のスクリプトでは直接、数値や文字列を使わずに、print文で変数を指定することで、それらを出力します。
このスクリプトは入力データなしに、awkで実行するため、BEGIN部に記述しています(以下も同様)。おーくの友だちで、新しくスクリプトファイル 4-1を作り、Input欄 Null Output欄 Screen で実行してみて下さい。結果が
2 abc
と表示されるでしょう。以下同様に、スクリプトは実際に実行してみることをお勧めします。awkは道具、ツールであって、よく使って手に馴染ませなければなりません。
また、ある変数の値を別の変数に代入することも出来ます。また計算式の値を代入することも出来ます。
# script4-2 BEGIN{ x = 2 # x は 2 となる y = x # y も 2 となる print y }
# script4-3 BEGIN{ x = 2 # x は 2 となる y = 3 # y は 3 となる z = x + y # z に x + y という式の値を代入、5 となる print z }
代入自体は簡単な手続きですが、ここでよく注意しておかないといけないのは、= は学校で習う数学の等号ではなく、代入を表す記号だと言うことです。等号で左右を結んだ等式は、左辺と右辺が等しいという判断を示すものですが、代入記号で結ばれた代入文は、代入と言う処理を意味します。たとえば次のようなスクリプトを見てください。
# script4-4 BEGIN{ x = 3 x = 7 print x }
もし、= を等号だと考えると、このスクリプトは意味をなしません。x は 最初 3 と等しく、次に 7 と等しいと言っていることになりますから、このスクリプトを書いたプログラマは寝ぼけているのか、ということになりかねません。しかし、これらの式は代入文ですから、何の問題もありません。awkでは、最初の x = 3 は x に 3 を代入すること、x が 3 という値を持つようになることを意味します。次に、その x に 7 を代入します。そうすると今度は、x は 7 という値をもちます。実際にこういうスクリプトを書けば、最初の x = 3 という式は無駄になりますが、別に文法的、論理的に間違っているわけではありません。print x で、x が現在保有している値の 7 が出力されます。
(注)「等しい」ということを表す記号は、awkでは、C言語などと同じく、== と書きます。これについては後に解説します。
ここが、今回、一番注意して読んで欲しいところです。特に、他のプログラミング言語の知識がある人は注意してください。これはawkの変数が多くのプログラミング言語の変数と全く異なるところですから。
awkの変数の中身は、スクリプトの中で、文脈に従って、数値としても文字列としても扱われます。あるいはawkの変数は、数と文字列の二つの値をもっていると考えることが出来ます。たとえば次のスクリプトを実行してみて下さい。
# script4-5 BEGIN{ x = 2 y = 3 w = x y # ----(1) v = x + y # ----(2) print "w = " w print "v = " v }
おーくの友だちで実行してみて下さい。結果はこうなるでしょう。
w = 23 v = 5
(1) の式では、x と y は文字列として連結されます。
(2) の式では、x と y は数値として加算されます。
その結果が上のような違いになります。awkは変数に代入されたものを、スクリプトの文脈に従って適切に判断し、数値として扱うべきときは、数値として扱い、文字列として扱うときは文字列として扱います。(1)の式では、x とy の間になにもありません。つまり、これは文字列の連結式だとawkは理解し、x と y を文字列として扱います。(2)の式では、間に加算記号 + があるので、これは数としての演算だと判断し、x y を数として加算するわけです。なかなか賢いですね。awkの変数は数値と文字列値と二つの値をもっているということを忘れないようにしてください。ただし文字列を代入した変数の場合、その文字列がそのまま数に変換できない場合は、数値としては 0 と見なされます。script 4-1 の例での、変数とそこに代入されている値をより正確に図示すれば、以下のようになります。
2 と "2" 0 と "abc"
ここでもうひとつ、注意すべき点があります。変数はスクリプトの中に登場させるだけで、存在するようになると既に述べました。多くのプログラミング言語では、変数を使う前に、その変数に代入してよい値の種類(整数、小数、文字列などなど)を宣言し、実際に何らかの値を代入して初めて演算に用いられます。しかし、awkでは、そういう面倒なことなしに、いきなり使っても良いのです。つまり宣言も、代入することさえなしに、使ってもよいのです。
しかしちょっと待てよと注意深い読者は、思うかもしれません。変数が容器だとすると、代入なしに使うということは、容器になにもいれずに使うと言うことで、まるで、やかんに水を入れずに火にかけるようなもので、それはちょっと危ないのではないかと心配する人がいるかもしれません。確かに多くのプログラミング言語ではそんなことをしたら、エラーになるか警告を受けます。しかし、awkの場合は問題ありません。というのは、awkでは変数は、存在すると同時に、つまりスクリプトに現れると同時に、その値も与えられるからです。即ち、変数の誕生の時に、数値としては、0、文字列としては、"" つまり空っぽの文字列を持つものと見なされます。従って、スクリプトとしては次のものは全く正しいものです。
# script 4-6 BEGIN { z = x + y print z }
x も y も何も代入されないうちに、加算され、その結果がzに代入されています。このとき、xもyも、加算と言う算術演算を施されますから、""の空文字列ではなく、数値の 0 と見なされ、0 + 0 という演算の結果 z にも0 が代入されます。従って結果として、0 が出力されます。これとは異なって以下のように
# script 4-7 BEGIN{ z = x y print z }
とすれば、結果はどうなるかわかるでしょうか? 最初の式は x y つまり文字列の連結と見なされ、同時に、このとき x も y も空の文字列と見なされ、空の文字列が連結されます。空の文字列を連結しても、空の文字列ですから、z にも空の文字列が代入されます。その結果、print 文で 空の文字列が出力されます、即ちなにも表示されません。BEGIN部で実行して確かめてください。これらは全くawkの文法どおりの振る舞いです。
まとめれば、awkの変数は、生まれると同時に、0 と "" の二つの値をもち、代入によって、これらは変化するが、スクリプトの文脈に応じて、どちらか適切なものが使われる、と言うように理解して置けばよいでしょう。さらに数値に変換できない文字列が入っている変数は、それを数値として扱うときは、0 と見なされると念を押しておきましょう。
(注)時には、スクリプトの書き方によっては、awkにも、ある変数を、数として扱うべきか、文字列として扱うべきか判断ができない場合が生ずることがあります。ま、awkを困らせるくらい、人間は気まぐれと言うか、人間の世界は複雑と言うか、そういう場合も実際のスクリプトの中では起こります。そういう時は人間が教えてやらなければなりませんが、この問題はもう少し先で扱います。気になる人は、参考文献の『プログラミング言語AWK』p59を参照してください
結局awkの扱うデータは、変数か、直接的な数値か文字列(これらを変数に対して、定数と呼びます) です。
変数 組込み変数 か、ユーザの定義する変数
定数 数 か、 文字列
このうち、文字列定数は常に、ダブルクォーテイションで囲みます。
また 数定数の表示形式としては、そのまま数字と小数点を並べます。
(注)数の表示には、おなじみの整数や小数以外にも、16進数の表示や指数表示などがありますが、ここでは触れません。
今回はawkの変数について、見てきました。awkではこの変数を駆使してテキストの処理を行いますが、その結果を出力しなければテキスト処理は完結しません。すでに、print文で出力については見てきていますが、さらに、次回は、もうひとつの、より機能の豊富な、printf文について紹介して、データの出力の基本を固めます。