
Ubuntu日本語フォーラム

ログインしていません。
初歩的な感があるのでこちらで良いか解らないのですが、質問させてください。
使用しているubuntuは 10.10 desktop remixです。
以下のサンプルスクリプトをターミナルで実行した場合、ひと手間しないと桁揃えがうまくいきません。
サンプルスクリプト
#!/bin/bash
nihongo=(日 日本 日本語 日本語で 日本語です)
hankaku1=(aaaaa bbbbb ccccc ddddd eeeee)
hanzen=(fあfff gいggg hうhhh iえiii jおjjj)
hankaku2=(kkkkk lllll mmmmm nnnnn ooooo)
# 全角スペース("4個" "3個" "2個" "1個")
_space_=(" " " " " " " ")
# 全角を2byteとして桁揃え(Shift_JIS)
for i in `seq 0 5`
do
printf "%-10s %5s %6s %5s\n" ${nihongo[$i]} ${hankaku1[$i]} ${hanzen[$i]} \
${hankaku2[$i]}
done
# 全角を3byteとして桁揃え(UTF-8)
for i in `seq 0 5`
do
printf "%-15s %5s %7s %5s\n" ${nihongo[$i]} ${hankaku1[$i]} ${hanzen[$i]} \
${hankaku2[$i]}
done
# 桁揃えするには、全角を3byteとして文字の最大数まで全角スペースを入れる。
for i in `seq 0 5`
do
printf "%-15s %5s %7s %5s\n" ${nihongo[$i]}${_space_[$i]} ${hankaku1[$i]} \
${hanzen[$i]} ${hankaku2[$i]}
done
結果は以下の様になります。
日 aaaaa fあfff kkkkk
日本 bbbbb gいggg lllll
日本語 ccccc hうhhh mmmmm
日本語で ddddd iえiii nnnnn
日本語です eeeee jおjjj ooooo
日 aaaaa fあfff kkkkk
日本 bbbbb gいggg lllll
日本語 ccccc hうhhh mmmmm
日本語で ddddd iえiii nnnnn
日本語です eeeee jおjjj ooooo
日 aaaaa fあfff kkkkk
日本 bbbbb gいggg lllll
日本語 ccccc hうhhh mmmmm
日本語で ddddd iえiii nnnnn
日本語です eeeee jおjjj ooooo
表示文字幅の関係で乱れてるかもしれませんが、3つ目の出力の様に、全角スペースを入れる等しないと日本語の文字数が変動する
値を、正常に桁揃えする事ができません。
これはprintfの正常な挙動なのでしょうか?
man printfを見ると「解釈のしかたは C の printf(3) 関数と同じ」と書かれており、Cのprintf()関数でも同様の結果となります。
$ cat foo.c
#include <stdio.h>
int main()
{
char *strs[] = {"あ", "ああ", "あああ"};
int i;
for (i = 0; i < 3; i++) {
printf("%10s#\n", strs[i]);
}
}
$ cc foo.c
$ ./a.out
あ#
ああ#
あああ#
そのほかのプログラミング言語でも、だいたい同じですね。
簡単にいうと、3バイトの文字を2桁幅で表示しているためのずれです。
マルチバイト文字を2桁幅として(本当はそうとは限りませんが)桁を揃えるには、以下のようなロジックになるかと思います。
$ cat hoge.sh
#!/bin/bash
strpad() {
local clen=${#3}
local LANG=C
local blen=${#3}
local -i pad="$2 - (clen + (blen - clen) / 2)"
if ((pad > 0)); then
printf -v $1 "%s%*s" $3 $pad ' '
else
printf -v $1 "%s" $3
fi
}
for s in ああ あああああ あa; do
strpad s1 10 $s
echo "$s1#"
done
$ bash ./hoge.sh
ああ #
あああああ#
あa #
オフライン
返信ありがとうございます。
やはり3byteの文字を2桁表示で扱っているのが原因だったんですね。
疑問が解決してスッキリしました。
又、サンプルスクリプトまで記述して頂き、こうやるのかと大変参考になりました。
ありがとうございます。