终端中的退格和UTF8编码

时间:2015-04-28 07:38:19

标签: php utf-8 terminal

这是一个简单的PHP测试脚本:

// Get a string from terminal
echo "> ";
$string = trim(stream_get_line(STDIN, 999999, PHP_EOL));

// string to hex:
$hex='';
for ($i=0; $i < strlen($string); $i++)
{
    $hex .= dechex(ord($string[$i]));
}

echo "$string $hex\n";

拳头发射,我输入“Привет”:

gkuzovnikov@gkdevel:~$ php ~/test.php
> Привет
Привет d09fd180d0b8d0b2d0b5d182

下次发布时,我输入“Привет”然后按退格键,然后再次按“т”:

gkuzovnikov@gkdevel:~$ php ~/test.php
> Привет
Приве�т d09fd180d0b8d0b2d0b5d1d182

似乎当我按退格键时,只删除了输入序列中的一个字节,而所有字符都是两个字节的长度。

有没有办法从输入中获取字符串,因此用户可以在输入时更正它?

1 个答案:

答案 0 :(得分:1)

答案是检查配置中是否支持stty 扩展程序 iutf8,以及它是否在您遇到问题时生效

传统上,终端驱动程序在接收到擦除字符时从输入中删除单个字节。但是,UTF-8是一种多字节编码(每个字符多个字节),用户的期望更好地满足

  • 删除最后一个输入字符的所有字节(由终端驱动程序)和
  • 向左移动光标(通过终端仿真器)。

最初将stty扩展名添加为Linux内核补丁(请参阅2004 mailing list讨论),并且似乎在某些其他系统(例如OSX)中受支持。此stty命令在OSX 10.9上的xterm中运行,并在iutf8部分中显示iflags

bash-3.2$ stty -a
speed 38400 baud; 24 rows; 80 columns;
lflags: icanon isig iexten echo echoe echok echoke -echonl echoctl
        -echoprt -altwerase -noflsh -tostop -flusho pendin -nokerninfo
        -extproc
iflags: -istrip icrnl -inlcr -igncr ixon -ixoff -ixany -imaxbel iutf8
        -ignbrk -brkint -inpck -ignpar -parmrk
oflags: opost onlcr oxtabs onocr onlret
cflags: cread cs8 parenb -parodd hupcl -clocal -cstopb -crtscts -dsrflow
        -dtrflow -mdmbuf
cchars: discard = ^O; dsusp = ^Y; eof = ^D; eol = <undef>; eol2 = ^@;
        erase = ^H; intr = ^C; kill = ^U; lnext = ^V; min = 1; quit = ^\;
        reprint = ^R; start = ^Q; status = ^T; stop = ^S; susp = ^Z;
        time = 0; werase = ^W;

erase设置当然是“退格”键。