终端中的退格键和 UTF8 编码
Backspace and UTF8 encoding in 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
似乎当我按退格键时,输入序列中只有一个字节被删除,而所有字符都是两个字节长度。
有没有办法从输入中获取字符串,以便用户可以在键入时更正它?
答案是检查你的配置是否支持stty
extension iutf8
以及它是否生效你看到了问题。
通常,终端驱动程序在收到擦除字符时从输入中删除一个 字节。但是,UTF-8 是一种多字节编码(每个字符多个字节),
更能满足用户的期望
- 删除最后输入的所有字节字符(由终端驱动程序)和
- 向左移动光标(通过终端仿真器)。
stty
扩展最初是作为 Linux 内核补丁添加的(参见 2004 mailing list 讨论),并且似乎在其他一些系统中得到支持(OSX实例)。此 stty
命令在 OSX 10.9 的 xterm
中是 运行,并在 iflags
部分显示 iutf8
作为选项:
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
设置当然是"backspace"键。
这是一个简单的 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
似乎当我按退格键时,输入序列中只有一个字节被删除,而所有字符都是两个字节长度。
有没有办法从输入中获取字符串,以便用户可以在键入时更正它?
答案是检查你的配置是否支持stty
extension iutf8
以及它是否生效你看到了问题。
通常,终端驱动程序在收到擦除字符时从输入中删除一个 字节。但是,UTF-8 是一种多字节编码(每个字符多个字节),
更能满足用户的期望- 删除最后输入的所有字节字符(由终端驱动程序)和
- 向左移动光标(通过终端仿真器)。
stty
扩展最初是作为 Linux 内核补丁添加的(参见 2004 mailing list 讨论),并且似乎在其他一些系统中得到支持(OSX实例)。此 stty
命令在 OSX 10.9 的 xterm
中是 运行,并在 iflags
部分显示 iutf8
作为选项:
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
设置当然是"backspace"键。