此問題困擾已久。例如:
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 處理最保險。