- ベストアンサー
printfの書式指定での2バイト文字の巾
2バイト文字、1バイト文字どちらもありうる(構成が不明である)文字列をバイト単位で桁揃えして出力したいのですが、 use encoding 'cp932'; printf "|%2s\n|","あ"; printf "|%2s\n|","aa"; とすると、出力結果は当然 | あ| |aa| となって、桁が揃わないですよね。「バイト単位で2バイト分の巾」という指定を実現するにはどうしたらいいのでしょうか。日本語処理ではよくある問題だと思うのですが。
- みんなの回答 (2)
- 専門家の回答
質問者が選んだベストアンサー
ちょっと裏技的に use Encode ; binmode(STDOUT,":bytes") ; # バイトコードをそのまま出力させるように変更 printf "|%2s\n|",Encode::encode('cp932',"あ"); # cp932にencodeすれば、2バイト文字は「2バイト=2文字」扱いになる 既出の方法の方が汎用性はありますけど。
その他の回答 (1)
- _--_1l1_1_
- ベストアンサー率67% (102/152)
# 表示がくずれるので空白2文字を全角空白にしていることに注意 use strict; use warnings; use utf8; use Encode; use Encode::CJKConstants; my @hello_list = ( 'こんにちは、世界!!', 'Hello World!!', 'HELLO WORLD!!', 'こんにちは、World。', "コンニチハ 世界.", '世界,你好!' ); binmode STDOUT, ":encoding(utf8)"; for my $hello (@hello_list) { my $view_length = count_view_length($hello); my $char_length = length $hello; my $format = '%-' . ( 32 - ( $view_length - $char_length ) ) . 's :'; printf $format, $hello; print "\n"; } # result。等幅フォントで見れば : (コロン)が揃っている # こんにちは、世界!! : # Hello World!! : # HELLO WORLD!! : # こんにちは、World。 : # コンニチハ 世界. : # 世界,你好! : sub count_view_length { my $str = shift; my $view_length = 0; for my $char ( split q{}, $str ) { my $sjis_char = encode( 'sjis', $char ); if ( $char =~ m/\p{InBasicLatin}/ ) { $view_length += 1; } elsif ( $sjis_char =~ m/^$Encode::CJKConstants::RE{SJIS_KANA}$/ ) { $view_length += 1; } else { $view_length += 2; } } return $view_length; }
お礼
大変参考になりました。どうもありがとうございました。
お礼
とりあえずはこの方法が簡単そうですので採用させていただこうかと思います。 どうもありがとうございました。