單位分隔符 ASCII 字元(ASCII 31,八進位 37)在 Vim 中可見為^_
.但是,如果我將相同的文件列印到終端,則該字元是不可見的。這會導致一行上的字段黏在一起:
# In Vim and less:
first field^_second field^_last field
# cat the same file to terminal:
cat delim.txt
first fieldsecond fieldlast field
# print 2nd field with awk
cat delim.txt | awk 'BEGIN {FS = "\037"} {print $2}'
second field
我想我可以使用 cat -v 使單位分隔符號可見:
cat -v delim.txt
first field^_second field^_last field
但這是比較麻煩的。為什麼單位分隔符號在 Bash shell 中列印到 stdout 時沒有可見的表示形式?我甚至無法正確複製和貼上 shell 輸出;單位分隔符號在此過程中遺失。
答案1
單位分隔符 ( US
) 字符,也稱為IS1
,屬於cntrl
字符類,並且是不是在print
字元類別中。它是一個控製字符,用於將文字組織成群組,對於旨在利用該資訊的程序。一般來說,不可列印的字元在不同的程式或環境中可能會有不同的解釋和呈現。
您看到它在 Vim 中表示的原因^_
是因為 Vim 是一個互動式編輯器。只要將正確的二進位字元寫入磁碟,它就可以隨意呈現不可列印的字元。
您無法在 shell 中獲得相同的行為,因為 Unix shell 程式是為了操作純文字並將純文字相互傳遞而編寫的。當您cat
建立文件時,寫入終端的文字必須是文件中實際的內容。
這樣就將其留給終端設備來解釋該字元。事實證明,一些終端模擬器做使US
角色與其他角色不同。在gnome-terminal
(或任何vte
基於 的終端)中,字元將呈現為包含十六進位代碼的方塊001F
。在xterm
or中rxvt
,該字元確實是不可見的。
答案2
單位分隔符號的 ASCII 範圍為控製字元,因此沒有(或通常不應該)有視覺表示。
Vim 和其他一些編輯器會顯示它們,以便您可以編輯它們。正如您所注意到的,cat -v
它也顯示出來。手冊頁顯示,這-v
是 的縮寫形式--show-nonprinting
,這會導致它用可列印表示替換非列印字符,這不是文件的原始內容,因此如果輸出實際上是另一個程序,可能會導致麻煩。
您看到的表示形式已經暗示它是一個控製字元:前面帶有 a 的字元^
是Ctrl+ 字元的常見表示法,它是在終端機中產生該字元的組合鍵。例如,Ctrl+可以讓你在 vim 中輸入單位分隔符號。_但另一個編輯器或某些 GUI 檢視器可能會顯示十六進位代碼、佔位符或完全不同的內容。
由於您的終端不列印控製字符,因此在選擇文字時也不會複製它(換行符和製表符等空白字符在這裡是一個例外,它們也是控製字符)。複製時通常會忽略的終端控製字符的另一個示例是顏色代碼,它是一個ESC
字符,後跟用於為文字著色的代碼。
因此,要在終端上顯示字符,除了使用用某些可列印字符替換單位分隔符的程序之外,沒有其他方法。
答案3
如果你想改變的話,在其他(非常好的)答案的邊緣一點僅有的顯示文件內容時的控製字符^_
,您可能想要音譯它使用tr
實用程式(以及一些 bash 相容語法):
# Replace the control character US (^_) by *one* other character
$ cat my.file | tr $'\c_' ':'
如果您需要用“擴展”形式替換該控製字符,則需要sed
:
# Replace the control character US (^_) by any string
cat /tmp/f | sed s/$'\c_'/^_/g
請注意語法$'\cX'
:此語法通知您的(bash 相容 shell)取代對應的控製字元。看維基百科的控製字元別名列表使用“插入符號”。如果您不喜歡這種語法,您可能更喜歡使用八進位$'\037'
或十六進位$'\x1f'
表示法。