我试图弄清楚如何使用Term::ReadLine
从终端读取Unicode输入。事实证明,如果我在提示符处输入Unicode字符,则返回的字符串会因各种设置而异。 (我正在运行Ubuntu 14.10,并已安装Term::ReadLine::Gnu
)。例如(p.pl
):
use open qw( :std :utf8 );
use strict;
use warnings;
use Devel::Peek;
use Term::ReadLine;
my $term = Term::ReadLine->new('ProgramName');
$term->ornaments( 0 );
my $ans = $term->readline("Enter message: ");
Dump ( $ans );
在提示符下运行p.pl
并输入å
会产生输出:
Enter message: å
SV = PV(0x83a5a0) at 0x87c080
REFCNT = 1
FLAGS = (PADMY,POK,pPOK)
PV = 0x917500 "\303\245"\0
CUR = 2
LEN = 10
因此返回的字符串$ans
未设置UTF-8
标志。但是,如果我使用perl -CS p.pl
运行程序,则输出为:
Enter message: å
SV = PVMG(0x24c12e0) at 0x23050a0
REFCNT = 1
FLAGS = (PADMY,POK,pPOK,UTF8)
IV = 0
NV = 0
PV = 0x248faf0 "\303\245"\0 [UTF8 "\x{e5}"]
CUR = 2
LEN = 10
在$ans
上正确设置了UTF-8标志。所以第一个问题是:为什么命令行选项-CS
与使用编译指示use open qw( :std :utf8 )
不同?
接下来,我使用Term::ReadLine::Stub
选项测试了-CS
:
$ PERL_RL=Stub perl -CS p.pl
输出现在是:
Enter message: å
SV = PV(0xf97260) at 0xfd90c8
REFCNT = 1
FLAGS = (PADMY,POK,pPOK,UTF8)
PV = 0x10746e0 "\303\203\302\245"\0 [UTF8 "\x{c3}\x{a5}"]
CUR = 4
LEN = 10
并且输出字符串$ans
已被双重编码,因此输出已损坏。这是一个错误,还是预期的行为?
答案 0 :(得分:2)
正如Denis Ibaev在answer中解释的那样,问题是Term::ReadLine
没有读取STDIN
,它会打开一个新的输入文件句柄。作为调用binmode($term->IN, ':utf8')
的替代方法,事实证明,通过提供-CS
可以使命令行选项use open qw( :std :utf8)
或Term::ReadLine
开箱即用STDIN
。 }作为Term::ReadLine->new()
的参数,正如在这个问题的答案中所解释的那样:Term::Readline: encoding-question。
例如:
use strict;
use utf8;
use open qw( :std :utf8 );
use warnings;
use Term::ReadLine;
my $term = Term::ReadLine->new('Test', \*STDIN, \*STDOUT);
my $answer = $term->readline( 'Enter input: ' );
答案 1 :(得分:1)
Term::ReadLine
未读取STDIN
,opens new文件句柄。所以use open qw(:std :utf8);
没有效果。
你需要做这样的事情:
my $term = Term::ReadLine->new('name');
binmode($term->IN, ':utf8');
关于-CS
的更新:
选项-C
为魔术变量${^UNICODE}
设置了一些值。 -CS
(或-CI
)选项使表达式${^UNICODE} & 0x0001
成立。如果Term::ReadLine
为真,则输入字符串为${^UNICODE} & 0x0001
sets UTF-8 flag on。
注意,选项-CS
与binmode($term->IN, ':utf8')
不同。第一个只设置UTF-8标志,第二个设置字符串。