wc のようなもの

wc、再び - みずぴー日記にインスパイヤを受けて wc コマンドのようなものを作ります。 ここで「ようなもの」と記述していますが、awk では改行文字のバイト数や日本語などマルチバイト文字のバイト数を得る手段がありませんので、「ようなもの」と表現しています。

wc の記述方法はいろいろあると思うのですが、ここでは以下のようなスクリプトを作ってみました。

#! /usr/local/bin/nawk -f
# wc.awk
# wc コマンドのようなもの
# usage: nawk -f wc.awk file[s]

{
    lines[FILENAME]++;
    words[FILENAME] += NF;
    chars[FILENAME] += length($0) + 1;      # +1 は改行
}

END {
    for (i in lines) {
        print lines[i], words[i], chars[i], i;
        total_lines += lines[i];
        total_words += words[i];
        total_chars += chars[i];
    }

    print total_lines, total_words, total_chars, "total";
}

つまり、一旦連想配列に格納し、END ブロックで表示と合計を行うものです。

実行してみましょう。

$ nawk -f wc.awk wc.awk*
21 56 447 wc.awk~
21 56 447 wc.awk
42 112 894 total

さて、本家 wc ではどう表現されるでしょうか。

$ wc wc.awk*
 21  56 447 wc.awk
 21  56 447 wc.awk~
 42 112 894 total

合致していますが、gawk ではマルチバイト文字は文字単位でカウントされるため、値が異なります。

$ gawk -f wc.awk wc.awk*
21 56 421 wc.awk
21 56 421 wc.awk~
42 112 842 total

HP の awk には blength() という関数がありますし、古い jgawk では jlength() という関数が用意されていましたが、現在の gawk にはこうしたマルチバイト文字とアスキー文字を区別する手段が準備されていません。

tag_nawk.pngtag_nawk.pngtag_nawk.pngtag_nawk.png