2010-01-14 19 views
4

什麼是正確的方式來到這裏一個美麗的輸出(所有行相同的縮進)?如何正確地將UTF-8字符串與Perl的printf對齊?

#!/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 

回答

4

我還沒有能夠重現它,但鬆散地說,似乎發生的是它是一個字符編碼不匹配。很可能你的Perl源文件已經以UTF-8編碼保存。但是,您尚未在腳本中啓用use utf8;。所以它將每個非ASCII德文字符解釋爲兩個字符並相應地設置填充。但您運行的終端也處於UTF-8模式,因此字符可以正確打印。嘗試添加use warnings;,我打賭你會打印一條警告,如果加入use utf8;實際上可以解決問題,我不會感到驚訝。

+0

「使用警告;」已經存在了,當我添加「使用utf8」時,第三行看起來像這樣:「M h ig123456789」。從文件中讀取我有同樣的問題。 – 2010-01-14 16:15:49

+3

好吧,使用「binmode STDOUT」編碼(utf8)'「也可以工作。 – 2010-01-14 16:26:17

+0

@Dan:我啓用了警告,但我沒有收到任何警告。 – 2010-01-14 17:03:47

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; 
} 
+0

這個和更有用的@tchrist答案在 http://www.perl.com/pub/2012/05/perlunicook-unicode-column-width-for-printing.html – toddkaufmann 2015-07-23 16:54:43

2
#!/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); 
相關問題