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