【问题标题】:How can I properly align UTF-8 strings with Perl's printf?如何正确地将 UTF-8 字符串与 Perl 的 printf 对齐?
【发布时间】:2011-01-05 02:12:57
【问题描述】:

什么是获得漂亮输出的正确方法(所有行相同的缩进)?

#!/usr/bin/env perl
use warnings;
use strict;
use DBI;

my $phone_book = [ [ qw( name number ) ],
            [ 'Kroner', 123456789 ],
            [ 'Holler', 123456789 ],
            [ 'Mühßig', 123456789 ],
            [ 'Singer', 123456789 ],
            [ 'Maurer', 123456789 ],
];

my $dbh = DBI->connect( "DBI:CSV:", { RaiseError => 1 } );
$dbh->do( qq{ CREATE TEMP TABLE phone_book AS IMPORT( ? ) }, {}, $phone_book );

my $sth = $dbh->prepare( qq{ SELECT name, number FROM phone_book } );
$sth->execute;

my $array_ref = $sth->fetchall_arrayref();

for my $row ( @$array_ref ) {
    printf "%9s %10s\n", @$row;
}

# OUTPUT:

#   Kroner  123456789
#   Holler  123456789
# Mühßig  123456789
#   Singer  123456789
#   Maurer  123456789

【问题讨论】:

    标签: perl unicode encoding


    【解决方案1】:
        #!/usr/bin/env perl
    
        use warnings;
        use strict;
    
        use utf8; # This is to allow utf8 in this program file (as opposed to reading/writing from/to file handles)
    
        binmode( STDOUT, 'utf8:' ); # Allow output of UTF8 to STDOUT
    
        my @strings = ( 'Mühßig', 'Holler' ); # UTF8 in this file, works because of 'use utf8'
    
        foreach my $s (@strings) { printf( "%-15s %10s\n", $s, 'lined up' ); } # should line up nicely
    
        open( FILE, 'utf8file' ) || die("Failed to open file: $! $?");
    
        binmode( FILE, 'utf8:' );
    
        # Same as above, but on the file instead of STDIN
    
        while(<FILE>) { chomp;printf( "%-15s %10s\n", $_, 'lined up' ); }
    
        close( FILE );
    
        # This works too
        use Encode;
    
        open( FILE, 'utf8file' ) || die("Failed to open file: $! $?");
    
        while(<FILE>) {
                chomp;
                $_ = decode_utf8( $_ );
                printf( "%-15s %10s\n", $_, 'lined up' );
        }
    
        close( FILE );
    

    【讨论】:

      【解决方案2】:

      如果您的代码点采用 0 或 2 个打印列而不是 1,则您不能将 Unicode 与 printf 一起使用,而您似乎这样做了。

      您需要改用Unicode::GCString

      错误的方式:

      printf "%-10.10s", our $string;
      

      正确的方式:

      use Unicode::GCString;
      
      my $gcstring = Unicode::GCString->new(our $string);
      my $colwidth = $gcstring->columns();
      if ($colwidth > 10) {
          print $gcstring->substr(0,10);
      } else {
          print " " x (10 - $colwidth);
          print $gcstring;
      }
      

      【讨论】:

      【解决方案3】:

      我无法重现它,但粗略地说,似乎正在发生的是字符编码不匹配。您的 Perl 源文件很可能已以 UTF-8 编码保存。但是,您尚未在脚本中启用 use utf8;。因此,它将每个非 ASCII 德语字符解释为两个字符并相应地设置填充。但是您正在运行的终端也处于 UTF-8 模式,因此字符打印正确。尝试添加use warnings;,我敢打赌你会得到一个警告,如果添加use utf8;真的能解决问题,我不会感到惊讶。

      【讨论】:

      • "使用警告;"已经存在,当我添加“使用 utf8”时,第三行看起来像这样:“M�h�ig 123456789”。从文件中读取我有同样的问题。
      • 好的,启用 "binmode STDOUT, 'encoding(utf8)'" 也可以。
      • @Dan:我启用了警告,但没有收到任何警告。
      猜你喜欢
      • 2011-08-25
      • 2019-11-07
      • 1970-01-01
      • 2020-04-22
      • 2013-06-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-09
      相关资源
      最近更新 更多