講座「文系のためのawkプログラミング入門」
関数については前々回で述べたように、あるデータを与えると、それに何らかの処理や加工を施して必要な形にして返してくれる、便利な小道具と考えればよいでしょう。後に見るように、awkではプログラマが自分で関数を書くこともできますが、今回はawkの提供してくれる文字列を処理する関数について学びましょう。これらはテキスト処理では算術関数よりもはるかに使う機会の多いものです。また、算術関数より、少し複雑です。文字列を加工するものや、文字列に関する情報を教えてくれるものなど機能もさまざまです。引数(関数に与えるデータです)の数も異なります。
まず紹介するのは、文字列に関して、情報を返してくれる関数です。次のようなものがあります。簡単なものから見ていきます。
これは引数として与えられた文字列 str の長さを返してくれます。
長さはコンピュータのデータの大きさを数えるときのバイト(byte)という単位であらわされます。長さをあらわすからと言って、1バイトとは何センチになるのか、などと聞かないで下さいね。コンピュータでは、全てのデータは、メモリに置かれますが、そのときどれだけのメモリを占有するかをこのバイトという単位は表しています。メモリの1バイトとは、半角の英数字一つが占めるメモリの大きさだ考えてください。1バイトは、さらにビット(bit)というコンピュータの最小のデータ単位が8個集まったものです。
1バイト = 8ビット
英語の半角英数字はこの8ビットの情報量ですべて表すことができます。しかし日本語は文字数が多くて(これは韓国語や中国語でも同じですが)8ビットでは表しきれず、いわゆる全角文字一つが16ビットすなわち、2バイトのメモリを占有します。 だからコンピュータに、"cat" という単語の長さはいくらかと聞けば、3 バイト と答えてくれますが、"日本語"という単語はどうだと聞くと、6 バイト と答えてくれます。コンピュータ上でファイルの大きさを表すときもこのバイトと言う単位を使いますね。約1000バイトが1キロバイト、約1000000バイトが1メガバイトです。
半角英数字は一文字を 1バイトと数える
日本語のひらがな・カタカナ・漢字は一文字を 2バイトと数える
このことを理解して、length()関数の使い方をみます。下のスクリプトを検討し、実行して試してください。
# script 8-1 BEGIN{ x = length("lemon") print "x = " x y = "egg" z = length(y) print "z = " z print length("おーくの友だち") }
すぐわかりますね。念のために注意しておくと、文字列関数を使うときに、引数として文字列をそのまま与える場合は常に "" で囲む必要があるということです。
この関数は引数として二つの文字列を受け取ります。二つの引数の間には、コンマを入れます。コンマの前後に半角空白を適宜挿入してもかまいません。最初の、第1引数である string の中に、第2引数の str が部分文字列として含まれているとき、その位置、すなわち何文字目から始まるかを返します。含まれていなければ 0 を返します。位置の数え方は最初の文字を1として数えます。たとえば "programming" という文字列には "gram" と言う文字列が部分文字列として含まれます。何文字目から始まるかと言うと、4文字目からですね。アルファベット1文字は1バイトと数えるので、この関数では4と言う答えが返ってきます。
(注)文字列のなかの文字の位置を数えるとき、C言語などでは1文字目を0と数えますが、awkは1とします。この点はC言語の経験者には要注意です。
# script 8-2 BEGIN{ print index("programming","gram") print index("gram","programming") }
このスクリプトを実行すれば、一行目に 4 二行目に 0 と出力されます。この関数のように、二つ以上引数があるときは、それぞれの引数の意味と、引数を並べる順序を理解していなければなりません。この index 関数では、第1引数に文字列全体を与え、第2引数には探したい部分文字列を与えます。
# script 8-3 BEGIN{ str1 = "computer" str2 = "ter" pos = index(str1,str2) print pos }
スクリプト実行の結果はわかりますね。文字列を変数に格納して、それを引数として、index関数を使っています。
# script 8-4 BEGIN{ str1 = "プログラミング言語AWK" str2 = "言語" print index(str1,str2) }
第一の引数 str という文字列の中で、第二の引数 reg であらわされる正規表現のパターンが適合する位置を返します。この関数で注意するのは、単に、返値を返すだけでなく、そのときawkの組み込み変数 RSTART(適合した最初の文字位置)とRLENGTH(適合した部分文字列の長さ)をセットします。
また、上の index との違いに気をつけてください。index 関数の第二の引数は特定の文字列ですが、match の第二引数は正規表現です。 次のスクリプトは programming という 文字列の中で、/g.*m/ という正規表現にマッチする部分文字列を探します。正規表現で/./ は任意の文字に、/*/は0個以上繰り返しを表します。g と m の間に任意の文字がなくても、いくつあっても良いということを意味します。
# script 8-5 BEGIN{ y = match("programming",/g.*m/) print "y = " y print "RSTART = " RSTART print "RLENGTH = " RLENGTH }
実行してみて下さい。
y = 4 RSTART = 4 RSTART = 5
という結果になります。最後の RLENGTH が5になることに注意してください。awkの正規表現のマッチングは、マッチする文字列のうち、もっとも長いものを選び出します。この例では、/g.*m/ という正規表現は
gram gramm
両方にマッチするわけですが、このうち長いものが選ばれます。
今回は、awkの文字列関数のうち、文字列についての種々の情報を教えてくれる関数を三つ学びました。次回は、文字列を加工する関数を見ます。