本書は連載「「シェル芸」に効く AWK処方箋」を単行本化したもので、本記事はその連載の第4回を加筆修正したものです。
第4章 AWKで一番の得意ワザ! シェルで文字列を自在に扱うための文字列関数
AWKの最も得意とするものは文字列処理だと言われています。従来、Unix上で文字列を処理する一般的な方法は、sedコマンドをはじめ、非常に特化した文法を有するプログラムで処理することでした。しかし、AWKの登場により汎用的でC言語ライク な、人が理解しやすい記述を行えるようになり、文字列処理の生産性が向上しました。ここではその文字列処理について説明します。また、AWKの生みの親の一人であるBrian Kernighan大先生からも提案された、ある変更についてもお知らせします。
4.1 文字列の抜き出し
データ処理の基本は「データを加工・集計してまとめる」こと、つまり「元のデータから必要な部分を抜き出して加工する」ことです。フィールド単位で抜き出す方法は前章で説明しました。本章はフィールド単位ではなく、「○文字目から○文字を抜き出す」といった処理から説明します。
この「○文字目から○文字を抜き出す」処理を行うには、substr()関数を使います。では、2文字目から後の文字列を取得してみましょう。
$ echo 'abcde' | awk '{print substr($0, 2)}' bcde
このようにsubstr()関数は、最初の引数に対象文字列、2番目の引数に、2文字目からであれば2を与えることで、必要な文字列を抜き出すことができます。
この短縮形として以下のようにも書けます。「シェル芸」で使うとキーの打数が少なくなり効率的です。
$ echo 'abcde' | awk '$0 = substr($0, 2)' bcde
substr()関数には3番目の引数を与えることもできます。この3番目の引数を指定すると、指定した文字数分だけの文字列を取り出すことができます。では、2文字目から3文字を取得してみましょう。
$ echo 'abcde' | awk '{print substr($0, 2, 3)}' bcd
他の言語にもsubstr()関数や、それに似た関数があります。ただ、多くの言語は0から数え始める「ゼロオリジン」です。一方、AWKは1から数え始める「1オリジン」であるため、人間の思考に近いイメージで引数を与えることができます。これはレコードやフィールドについても同じですし、AWKに関する全てのインデックスは1から開始されます。もっとも、逆に分かりにくいという方も多いようです。
よく使われる方法として、「対象文字列の中にある特定の文字列から任意の文字列を取り出す」または「ある文字列までの任意の文字列を取り出す」というものがあります。このような場合には、index()関数を併せて用いると効果的です。
$ echo 'abcde' | awk '{print substr($0, index($0, "b"))}' bcde
この例では文字列bから最後までを抜き出すのに、substr()関数とindex()関数の両方を用いています。
index()関数は最初の引数に対象となる文字列、2番目の引数に検索したい文字列を指定すると、検索したい文字列の先頭位置を返します。検索文字列が存在しない場合には0を返します。
このsubstr()関数とindex()関数の組み合わせは、文字列の抜き出しの中でも特に多く用いられるテクニックなので、覚えておくと便利です。
4.2 文字列の検索
文字列検索や正規表現検索を行うスクリプトはすでに紹介しましたね。
……
※この続きはCodeZine掲載時の本稿、あるいは加筆修正された本書をご覧ください。