Terminal

Ctrl-J 的特殊處理

  • January 7, 2022

當我按下Ctrl-V Ctrl-J外殼(在 下urxvt)時,它會開始一個新行(將游標定位在新行的開頭),而不是列印^J.

vim它列印^@

同樣的情況也出現在虛擬控制台中。

顯然有些東西預處理Ctrl-J。它是什麼,我如何影響它?

$ stty -a
speed 38400 baud; rows 26; columns 101; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>;
eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R;
werase = ^W; lnext = ^V; discard = ^O; min = 1; time = 0;
-parenb -parodd -cmspar cs8 -hupcl -cstopb cread -clocal -crtscts
-ignbrk brkint ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff
-iuclc -ixany imaxbel iutf8
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt
echoctl echoke -flusho -extproc

$ echo $TERM
rxvt-unicode-256color

$ urxvt --help |&  head -1
rxvt-unicode (urxvt) v9.26 - released: 2021-05-14

UPD我正在配置tmux,這種行為讓我認為這bind-key C-j send-keys C-j不起作用。

正如 Arkadiusz Drabczyk 所說,readline負責處理C-v. 特別是C-v C-j。它只是以不同的方式處理它們。據說是因為( ) 可以在沒有符號的情況下以有意義的方式表示。如果您好奇的話,該符號中的字母是通過對字元程式碼進行或運算獲得的。或者您可能會說,對應於,to ,等等。C-j``Enter``^*0x400x01``^A``0x02``^B

至於vim那個 ( ^@) 也是它表示換行符的方式。文件中提到了幾點:

您也可以使用與 .<NL>相同的方式來分隔命令'|'。插入一個<NL>使用CTRL-V CTRL-J"^@"將顯示。

https://github.com/vim/vim/blob/v8.2.4027/runtime/doc/cmdline.txt#L652-L653

NL-used-for-Nul

技術細節: <Nul>文件中的字元儲存<NL>在記憶體中。在顯示屏中,它們顯示為"^@"。翻譯是在讀寫文件時完成的。要將 a<Nul>與搜尋模式匹配,您只需輸入CTRL-@或 即可"CTRL-V 000"。這可能正是您所期望的。<NL>在內部,該字元在搜尋模式中被替換為 a 。不尋常的是,打字CTRL-V CTRL-J也插入了 a <NL>,因此也在文件中搜尋 a <Nul>

https://github.com/vim/vim/blob/v8.2.4027/runtime/doc/pattern.txt#L1273-L1280

可能它與將空字節作為換行符儲存在記憶體中有關。

Bash 中的 Cv 由 readline 處理:

$ bind -p | grep '"\\C-v":'
"\C-v": quoted-insert

如 readline(3) 中所述:

  quoted-insert (C-q, C-v)
         Add the next character that you type to the line verbatim.  This
         is how to insert characters like C-q, for example.

您可以使用 Cv 插入其他字元,例如 Cv Ci 將插入製表符。要知道哪個字母產生給定的字元 open man ascii

      Oct   Dec   Hex   Char                        Oct   Dec   Hex   Char
      ────────────────────────────────────────────────────────────────────────
      000   0     00    NUL '\0' (null character)   100   64    40    @
      001   1     01    SOH (start of heading)      101   65    41    A
      002   2     02    STX (start of text)         102   66    42    B
      003   3     03    ETX (end of text)           103   67    43    C
      004   4     04    EOT (end of transmission)   104   68    44    D
      005   5     05    ENQ (enquiry)               105   69    45    E
      006   6     06    ACK (acknowledge)           106   70    46    F
      007   7     07    BEL '\a' (bell)             107   71    47    G
      010   8     08    BS  '\b' (backspace)        110   72    48    H
      011   9     09    HT  '\t' (horizontal tab)   111   73    49    I
      012   10    0A    LF  '\n' (new line)         112   74    4A    J
      013   11    0B    VT  '\v' (vertical tab)     113   75    4B    K
      014   12    0C    FF  '\f' (form feed)        114   76    4C    L
      015   13    0D    CR  '\r' (carriage ret)     115   77    4D    M

如您所見, J 與新行位於同一行,而 I 與水平製表符位於同一行。

您可以使用其他範例來檢查自己,例如 Cv Cg 會產生 bell:

$ printf ^G| hexdump -C
00000000  07                                                |.|
00000001

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