此问题困扰已久。例如:
read var <Enter>
此时输入中文,例如“加由”,欲修改为“油”时,按backspace键,
萤幕却显示“由”只删除一半。请问此问题如何解决?
在bash、zsh下都是如此。
哪种 linux 系统版本? 本机还是远端操作环境?有无在 xwindow 内?
楼主: franzhuang (dave) 2022-05-23 21:00:00
Fedora和pop都测试过了,都是如此,是在本机的x windo
作者:
OrzOGC (洞八达人.拖哨天王)
2022-05-23 22:42:00我用fedora很正常啊?
作者:
bitlife (BIT一生)
2022-05-23 22:44:00测了一下ubuntu 20.04 bash也有这现象,应该是backspace删掉1个中文字但光标却只回移1个半角英数宽度,按backspace2次[加由]两字应该已经删除,但萤幕却还留了一个字,再按bs光标也不会再回移
换 terminal 呢? 例如 kitty 或 alacritty
楼主: franzhuang (dave) 2022-05-24 06:35:00
测试过tilix gnome-terminal ,也安装alacritty测试,问题一样。改字体也是。回去用Fedora确认,也是如此bash, zsh都有这问题,fish正常,导致script中必须呼叫fish来read中文输入。蛮困扰的,另外,在terminal下,python的input()有同样问题python input()有此问题,是指在terminal执行pythonscript,不是python shell
作者:
lantw44 (#######################)
2022-05-24 07:26:00用 bash 的话可以加 -e 让它用 Readline 函式库处理输入在没有输入函式库辅助的环境下,按一次 backspace 就是退1 格和删除 1 byte 的资料,但你的“由”分别占了 2 格和3 byte 的空间,所以萤幕显示会和实际送进程式的内容不同实际上你应该要按 3 次 backspace,把画面上的“加”也吃掉一半,再输入“油”,程式看到的才会是“加油”。
楼主: franzhuang (dave) 2022-05-24 11:11:00
测试read e var,以及read -e var,呈现的情形相同。
楼主: franzhuang (dave) 2022-05-24 13:09:00
安装mlterm,使用您的设定档,情形大致如同先前。
作者:
lantw44 (#######################)
2022-05-24 21:10:00如果 read -e 没效,那可能要检查你使用的 locale 是不是用 UTF-8 编码了。照理说你的环境应该要是 UTF-8,不然连gnome-terminal 都开不起来。先说 read -e 只在 bash 有用,我不知道 zsh 要怎么用。
楼主: franzhuang (dave) 2022-05-24 22:03:00
非常感谢,确实我用的是zsh,bash下read -e完美解决我平常用zsh,但是script是用bash写的,所以此法适用这个问题很困扰的原因,除了read以外,C++的cin也有同同样情形,python input()在bash下执行也是
作者:
lantw44 (#######################)
2022-05-24 23:26:00因为系统默认的输入界面就是那个样子,kernel 并没有内建Unicode 数据库,无法处理现今复杂的文字和编码系统。因此如果需要提供使用者比较好的输入界面,就要靠外部函式库,像是 bash 和 python 的交互式界面都是用 readline。好像不应该说没有内建 Unicode 数据库,应该是说不是拿来用在这个地方,毕竟处理大小写还是会用到 Unicode 资料。总之如果是你自己的程式要提供好用的接口,那你的程式本身应该要去呼叫外部函式库,同时也要注意授权。如果是别人的程式没用相关函式库造成很难操作,可以试试 rlwrap。
楼主: franzhuang (dave) 2022-05-25 09:34:00
谢谢,原来如此。也谢谢以上大家协助测试。
这个问题曾有人提出过,也是用 Fedora 的,是用read -e 解决。比较奇怪的是,我在 FreeBSD 测试过多种 terminal,不会有这个问题。显然可能和较底层的lib 甚至 kernel 有关。BTW,我所谓不会有问题是指中文感长度不会误判,但一个中文字还是要 bs 二次才会删除。s/感长度/总长度/g
zsh 可以用 vared 就好, ex: vared -c varnamevarname 若是已经存在会带入,要空值就先 unset 一次
作者:
lantw44 (#######################)
2022-05-26 01:17:00FreeBSD 我用起来跟 Linux 行为一样耶,都是几个 byte 就要按几次 backspace。如果你是用 Big5 一个字 2 byte 那还能跟萤幕宽度对起来,用 UTF-8 一个字 3 ~ 4 byte 就对不起来了。
你说的那个是程式意义上所占的空间,并不是萤幕上呈现的几何度量。不管什么编码,在萤幕呈现上,terminal 固定字型,以英文字是一个单位的话,那么中文字就是二个单位。在 X/terminal/bash 互动下执行 read var 按 Enetr,然后输入三个中文字,FreeBSD 会被解读成六个英文字(虽显示是正确)可以 bs 六次删除。但在 Linux 大多数的 terminal 会被解读成三个英文字,bs 往后删的时候,删到一个半中文字就停了,无法再向后删。我觉得这是 i18n 化时的漏洞。才会出现半个中文字。我会建议 mlterm 是它也会解读成六个英文字,可以正确 bs 六次删除。也就是说虽没认出是中文字,但勉强可用。
作者:
lantw44 (#######################)
2022-05-29 23:22:00刚才实际测试,在 Linux 下如同你说的按三次 backspace就全部删完了,只是光标位置不对,停在一个半的地方。在 FreeBSD 下则是按九次 backspace 才成功让 read 读到空字串,但光标在按六次的时候就已经回到行首了,所以依然有光标位置错误的问题。在 FreeBSD 下如果只按六次,虽然可以让画面中的字全部消失,但 read 还是会读到一个字
你说的对,之前我偷懒没去验证 var 的值,造成误判。看来还是交给 readline 处理最保险。