Bash

如何在 shell 中以不同方式顯示控製字元(^C、^D、^[、…)

  • November 22, 2015

當您在 shell 中鍵入控製字元時,它們會使用所謂的“插入符號”來顯示。例如,轉義被寫成^[插入符號。

我喜歡定制我的 bash shell 讓它看起來很酷。例如,我改變了我的PS1PS2變得有色。我現在希望控製字元也具有獨特的外觀,以使它們與正常字元更容易區分。

$ # Here I type CTRL-C to abort the command.
$ blahblah^C
         ^^ I want these two characters to be displayed differently

有沒有辦法讓我的 shell 以不同的方式突出顯示控製字元?

是否可以使它以粗體顯示它們,或者使它們以與正常文本不同的顏色顯示?

我在這裡使用bash shell,但我沒有標記問題,bash因為也許有一個適用於許多不同 shell 的解決方案。

請注意,我不知道控製字元的突出顯示發生在什麼級別。我首先認為它在外殼本身中。現在我聽說它是readline控制控製字元在 shell 中的方式,如bash。所以這個問題現在被標記了readline,我仍在尋找答案。

當您按下 時Ctrl+X,您的終端仿真器會將字節 0x18 寫入偽終端對的主端。

接下來會發生什麼取決於如何配置 tty 線路規程(核心中的一個軟體模組,位於主端(在模擬器的控制下)和從端(在終端中執行的應用程序與之互動)之間)。

配置該tty 線路規程的命令是stty命令。

cat當執行一個不知道也不關心它的標準輸入是否是終端的愚蠢應用程序時,終端處於預設規範模式,其中 tty 行規程實現了粗略的行編輯器

一些需要比粗線條編輯器更多的互動式應用程序通常會在啟動時更改這些設置,並在離開時恢復它們。現代 shell在它們的提示下就是此類應用程序的範例。他們實現了自己的更高級的行編輯器。

通常,當您輸入命令行時,shell 會將 tty 行規則置於該模式,當您按下輸入鍵執行目前命令時,shell 會恢復正常的 tty 模式(就像在發出提示之前一樣)。

如果您執行該命令,您將看到啞應用程序stty -a正在使用的目前設置。您可能會看到和設置已啟用。icanon``echo``echoctl

這意味著:

  • icanon:啟用了粗線編輯器。
  • echo:您鍵入的字元(終端仿真器寫入主端)被顯(可供終端仿真器讀取)。
  • echoctl:控製字元不是被回顯,而是被**回顯為^X.

因此,假設您鍵入A B Backspace-aka-Ctrl+H/? C Ctrl+X Backspace Return.

您的終端仿真器將發送:AB\bC\x18\b\r. 行規則將顯: ,並且從從屬端 ( )AB\b \bC^X\b \b\b \b\r\n讀取輸入的應用程序將讀取./dev/pts/x``AC\n

應用程序看到的只是AC\n,並且只有當您按下它時Enter,它才能對^X那裡的輸出進行任何控制。

您會注意到對於echo,第一個^H^?對於某些終端,請參閱erase設置)導致\b \b被發送回終端。這是將游標向後移動、用空格覆蓋、再次向後移動游標的順序,而第二個導致^H擦除\b \b\b \b這兩個字元。^``X

( ^X0x18) 本身正在被轉換^X輸出。就像B,它沒有進入應用程序,因為我們用 Backspace 刪除了它。

\r(aka ^M) 被翻譯成\r\n( ^M^J) 表示迴聲,而\n( ^J) 表示應用程序。

那麼,對於那些愚蠢的應用程序,我們有哪些選擇:

  • 禁用echo( stty -echo)。這有效地改變了控製字元的回顯方式,通過…不回顯任何內容。不是真正的解決方案。
  • 禁用echoctl. 這改變了控製字元(除了^H, ^M… 以及行編輯器使用的所有其他字元)的回顯方式。然後它們按原樣回顯。也就是說,例如,ESC 字元作為\e( ^[/ 0x1b) 字節發送(終端將其辨識為轉義序列的開始),^G您發送一個\a(BEL,使您的終端發出嗶嗶聲)……不是一個選項.
  • 禁用粗線編輯器 ( stty -icanon)。這不是一個真正的選擇,因為原始應用程序將變得不那麼可用。
  • 編輯核心程式碼以更改 tty 行規則的行為,以便控製字元的顯發送\e[7m^X\e[m而不是僅發送^X(這里\e[7m通常在大多數終端中啟用反向影片)。

一種選擇可能是使用像rlwrap這樣的包裝器,這是一種骯髒的技巧,可以將花哨的行編輯器添加到愚蠢的應用程序中。實際上,該包裝器試圖將read()終端設備中的 simple s 替換為對 readline 行編輯器的呼叫(這確實改變了 tty 行規則的模式)。

更進一步,您甚至可以嘗試像這樣的解決方案,它會劫持來自終端的所有輸入以通過 zsh 的行編輯器(恰好^X在反向影片中突出顯示 s),這依賴於 GNU 螢幕的:exec功能。

現在對於實現自己的行編輯器的應用程序,由他們決定如何完成顯。bash將 readline 用於不支持自定義控製字元如何回顯的內容。

對於zsh,請參見:

info --index-search='highlighting, special characters' zsh

zsh預設情況下會突出顯示不可列印的字元。您可以自定義突出顯示,例如:

zle_highlight=(special:fg=white,bg=red)

對於那些特殊字元的紅色突出顯示白色。

但是,這些字元的文本表示是不可定制的。

在 UTF-8 語言環境中,0x18 將呈現為^X, \u378, \U7fffffff(兩個未分配的 unicode 程式碼點)為<0378>, <7FFFFFFF>, \u200b(一個不可列印的 unicode 字元)為<200B>.

\x80在 iso8859-1 語言環境中將呈現為^�… 等。

引用自:https://unix.stackexchange.com/questions/239808