看板 Linux 關於我們 聯絡資訊
此問題困擾已久。例如: read var <Enter> 此時輸入中文,例如「加由」,欲修改為「油」時,按backspace鍵, 螢幕卻顯示「由」只刪除一半。請問此問題如何解決? 在bash、zsh下都是如此。 -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 1.175.107.43 (臺灣) ※ 文章網址: https://www.ptt.cc/bbs/Linux/M.1653290140.A.CDF.html
kenduest: 哪種 linux 系統版本? 本機還是遠端操作環境?有無在 x 05/23 18:48
kenduest: window 內? 05/23 18:48
franzhuang: Fedora和pop都測試過了,都是如此,是在本機的x windo 05/23 21:00
OrzOGC: 我用fedora很正常啊? 05/23 22:42
bitlife: 測了一下ubuntu 20.04 bash也有這現象,應該是backspace刪 05/23 22:44
bitlife: 掉1個中文字但游標卻只回移1個半形英數寬度,按backspace 05/23 22:45
bitlife: 2次[加由]兩字應該已經刪除,但螢幕卻還留了一個字,再按bs 05/23 22:46
bitlife: 游標也不會再回移 05/23 22:46
asas1asas200: 換 terminal 呢? 例如 kitty 或 alacritty 05/24 01:35
franzhuang: 測試過tilix gnome-terminal ,也安裝alacritty測試 05/24 06:35
franzhuang: ,問題一樣。改字體也是。回去用Fedora確認,也是如此 05/24 06:37
franzhuang: bash, zsh都有這問題,fish正常,導致script中必須呼 05/24 06:54
franzhuang: 叫fish來read中文輸入。蠻困擾的,另外,在terminal下 05/24 06:55
franzhuang: ,python的input()有同樣問題 05/24 06:55
franzhuang: python input()有此問題,是指在terminal執行python 05/24 07:01
franzhuang: script,不是python shell 05/24 07:01
lantw44: 用 bash 的話可以加 -e 讓它用 Readline 函式庫處理輸入 05/24 07:26
lantw44: 在沒有輸入函式庫輔助的環境下,按一次 backspace 就是退 05/24 07:33
lantw44: 1 格和刪除 1 byte 的資料,但你的「由」分別佔了 2 格和 05/24 07:34
lantw44: 3 byte 的空間,所以螢幕顯示會和實際送進程式的內容不同 05/24 07:36
lantw44: 實際上你應該要按 3 次 backspace,把畫面上的「加」也吃 05/24 07:37
lantw44: 掉一半,再輸入「油」,程式看到的才會是「加油」。 05/24 07:38
franzhuang: 測試read e var,以及read -e var,呈現的情形相同。 05/24 11:11
EdwardGJLee: 使用真正 multilingual 的 mlterm。 05/24 11:24
EdwardGJLee: http://mlterm.sourceforge.net/ 05/24 11:24
EdwardGJLee: https://tinyurl.com/4jn457dj 參考設定檔 05/24 11:26
franzhuang: 安裝mlterm,使用您的設定檔,情形大致如同先前。 05/24 13:09
lantw44: 如果 read -e 沒效,那可能要檢查你使用的 locale 是不是 05/24 21:10
lantw44: 用 UTF-8 編碼了。照理說你的環境應該要是 UTF-8,不然連 05/24 21:12
lantw44: gnome-terminal 都開不起來。 05/24 21:12
lantw44: 先說 read -e 只在 bash 有用,我不知道 zsh 要怎麼用。 05/24 21:18
franzhuang: 非常感謝,確實我用的是zsh,bash下read -e完美解決 05/24 22:03
franzhuang: 我平常用zsh,但是script是用bash寫的,所以此法適用 05/24 22:05
franzhuang: 這個問題很困擾的原因,除了read以外,C++的cin也有同 05/24 22:49
franzhuang: 同樣情形,python input()在bash下執行也是 05/24 22:50
lantw44: 因為系統預設的輸入界面就是那個樣子,kernel 並沒有內建 05/24 23:26
lantw44: Unicode 資料庫,無法處理現今複雜的文字和編碼系統。因 05/24 23:28
lantw44: 此如果需要提供使用者比較好的輸入界面,就要靠外部函式 05/24 23:29
lantw44: 庫,像是 bash 和 python 的互動式界面都是用 readline。 05/24 23:29
lantw44: 好像不應該說沒有內建 Unicode 資料庫,應該是說不是拿來 05/24 23:35
lantw44: 用在這個地方,畢竟處理大小寫還是會用到 Unicode 資料。 05/24 23:36
lantw44: 總之如果是你自己的程式要提供好用的介面,那你的程式本 05/24 23:37
lantw44: 身應該要去呼叫外部函式庫,同時也要注意授權。如果是別 05/24 23:40
lantw44: 人的程式沒用相關函式庫造成很難操作,可以試試 rlwrap。 05/24 23:41
franzhuang: 謝謝,原來如此。也謝謝以上大家協助測試。 05/25 09:34
EdwardGJLee: 這個問題曾有人提出過,也是用 Fedora 的,是用 05/25 12:44
EdwardGJLee: read -e 解決。比較奇怪的是,我在 FreeBSD 測試過多 05/25 12:45
EdwardGJLee: 種 terminal,不會有這個問題。顯然可能和較底層的 05/25 12:45
EdwardGJLee: lib 甚至 kernel 有關。 05/25 12:46
EdwardGJLee: BTW,我所謂不會有問題是指中文感長度不會誤判,但一 05/25 13:34
EdwardGJLee: 個中文字還是要 bs 二次才會刪除。 05/25 13:35
EdwardGJLee: s/感長度/總長度/g 05/25 13:35
kenduest: zsh 可以用 vared 就好, ex: vared -c varname 05/25 16:09
kenduest: varname 若是已經存在會帶入,要空值就先 unset 一次 05/25 16:10
lantw44: FreeBSD 我用起來跟 Linux 行為一樣耶,都是幾個 byte 就 05/26 01:17
lantw44: 要按幾次 backspace。如果你是用 Big5 一個字 2 byte 那 05/26 01:19
lantw44: 還能跟螢幕寬度對起來,用 UTF-8 一個字 3 ~ 4 byte 就對 05/26 01:19
lantw44: 不起來了。 05/26 01:19
EdwardGJLee: 你說的那個是程式意義上所佔的空間,並不是螢幕上呈 05/26 09:48
EdwardGJLee: 現的幾何度量。不管什麼編碼,在螢幕呈現上, 05/26 09:49
EdwardGJLee: terminal 固定字型,以英文字是一個單位的話,那麼中 05/26 09:50
EdwardGJLee: 文字就是二個單位。 05/26 09:50
EdwardGJLee: 在 X/terminal/bash 互動下執行 read var 按 Enetr, 05/26 09:51
EdwardGJLee: 然後輸入三個中文字,FreeBSD 會被解讀成六個英文字 05/26 09:51
EdwardGJLee: (雖顯示是正確)可以 bs 六次刪除。但在 Linux 大多 05/26 09:52
EdwardGJLee: 數的 terminal 會被解讀成三個英文字,bs 往後刪的時 05/26 09:53
EdwardGJLee: 候,刪到一個半中文字就停了,無法再向後刪。 05/26 09:56
EdwardGJLee: 我覺得這是 i18n 化時的漏洞。才會出現半個中文字。 05/26 09:57
EdwardGJLee: 我會建議 mlterm 是它也會解讀成六個英文字,可以正 05/26 09:58
EdwardGJLee: 確 bs 六次刪除。也就是說雖沒認出是中文字,但勉強 05/26 09:59
EdwardGJLee: 可用。 05/26 10:00
lantw44: 剛才實際測試,在 Linux 下如同你說的按三次 backspace 05/29 23:22
lantw44: 就全部刪完了,只是游標位置不對,停在一個半的地方。 05/29 23:22
lantw44: 在 FreeBSD 下則是按九次 backspace 才成功讓 read 讀到 05/29 23:23
lantw44: 空字串,但游標在按六次的時候就已經回到行首了,所以依 05/29 23:24
lantw44: 然有游標位置錯誤的問題。在 FreeBSD 下如果只按六次,雖 05/29 23:24
lantw44: 然可以讓畫面中的字全部消失,但 read 還是會讀到一個字 05/29 23:25
EdwardGJLee: 你說的對,之前我偷懶沒去驗證 var 的值,造成誤判。 05/30 14:41
EdwardGJLee: 看來還是交給 readline 處理最保險。 05/30 14:42