文字を中央に表示する

awk はテキストの整形にも便利なツールとして紹介されていますので、こうしたセンタリングのようなこともできます。 文字を中央に表示する - みずぴー日記 にインスパイヤされているわけですが、元の問題はC/C++の宿題を片付けます@wiki - Cの宿題/文字列操作になります。

さて、問題の内容は文字を中央に表示する - みずぴー日記に書かれているように以下のようなものを前提とします。

  • 文字列を入力されたら、それを中央に表示する
  • 単語間のスペースは1個にまとめる
  • 入力文字列の幅と、出力文字列の幅は同じ
#! /usr/local/bin/nawk -f
# centering.awk
# 文字列をセンタリングする
# usage: nawk -f centering.awk file[s]

{
    init_str_len = length($0);

    gsub(/^ +/, "", $0);
    gsub(/ +$/, "", $0);
    gsub(/ +/, " ", $0);
    old_str_len = length($0);

    num_before = int((init_str_len - old_str_len) / 2);
    num_after = init_str_len - old_str_len - num_before;

    print repeat_str(" ", num_before) $0 repeat_str(" ", num_after);
}

function repeat_str(str, num,   i, result) {
    for (i = 1; i <= num; i++) {
        result = result str;
    }
    return result;
}

実行してみましょう。 個人的な趣味の問題でもあるのですが、sed のセパレータは置換対象に "/" を含むケースのある (という気がする) Unix では "/" よりも "|" の方が誤引用が少ない気がします。

$ echo ' This   is  a    good   program   ' | sed 's| |_|g'
_This___is__a____good___program___

$ echo ' This   is  a    good   program   ' | nawk -f centering.awk | \
  sed 's| |_|g'
______This_is_a_good_program______

さて、日本語の場合には、nawk は length() 関数がバイト数を返し、gawk は length() 関数が文字数を返すのですが、上記プログラムでは問題ありません。

$ echo ' Today は  晴天なり   ' | sed 's| |_|g'
_Today_は__晴天なり___

$ echo ' Today は  晴天なり   ' | nawk -f centering.awk | sed 's| |_|g'
__Today_は_晴天なり___

$ echo ' Today は  晴天なり   ' | gawk -f centering.awk | sed 's| |_|g'
__Today_は_晴天なり___

tag_nawk.pngtag_nawk.pngtag_nawk.pngtag_nawk.png