Bash学习 - 第8章:Command Line Editing,第4-5节:Bindable Readline Commands

本文为 Bash Reference Manual第8章:Command Line Editing ,第4节:Bindable Readline Commands 和 第5节:Readline vi Mode 的读书笔记。

💡 由于 8.5 Readline vi Mode 内容极少,因此也包含在本篇笔记中。

本节介绍可能绑定到按键序列的 Readline 命令。您可以通过执行 bind -P 列出您的按键绑定,或者为了更简洁的格式,适合 inputrc 文件的,可以使用 bind -p。(参见 Bash 内建命令。)没有附带按键序列的命令默认是不绑定的。

在以下描述中,point 指当前光标位置,mark 指通过 set-mark 命令保存的光标位置。point 和 mark 之间的文本称为区域。Readline 有一个活动区域的概念:当区域处于活动状态时,Readline 重新显示会使用 active-region-start-color 变量的值高亮显示该区域。enable-active-region 变量用于开启或关闭此功能。有几个命令会将区域设为活动状态;这些命令将在下文中标出。

💡 本章凡是没有做按键绑定的(即括号内为空),都可以忽略不看。

完整的笔记目录参见Bash学习笔记总目录

8.4.1 Commands For Moving

beginning-of-line (C-a)

移动到当前行的起始位置。在某些键盘上,这也可能绑定到 Home 键。

end-of-line (C-e)

移动到行尾。在某些键盘上,这也可能绑定到 End 键。

forward-char (C-f)

向前移动一个字符。在某些键盘上,这也可能绑定到右箭头键。

backward-char (C-b)

向后移动一个字符。在某些键盘上,这也可能绑定到左箭头键。

forward-word (M-f)

向前移动到下一个单词的结尾。单词由字母和数字组成。

backward-word (M-b)

向后移动到当前或前一个单词的起始位置。单词由字母和数字组成。

shell-forward-word (M-C-f)

向前移动到下一个单词的结尾。单词由未引用的 shell 元字符分隔。

shell-backward-word (M-C-b)

向后移动到当前或前一个单词的起始位置。单词由未引用的 shell 元字符分隔。

💡 M-f/M-b和M-C-f/M-C-b的区别,以bind -v|grep enable-active-region为例,前者会将enable-active-region看作3个单词,后者只看作1个。

previous-screen-line ()

尝试将光标移动到上一物理屏幕行的同一列。如果当前 Readline 行不超过一行物理行,或者光标位置不大于提示符长度加屏幕宽度,这将不会产生预期效果。

next-screen-line ()

尝试将光标移动到下一物理屏幕行的同一列。如果当前 Readline 行不超过一行物理行,或者当前 Readline 行的长度不大于提示符长度加屏幕宽度,这将不会产生预期效果。

clear-display (M-C-l)

清除屏幕,并在可能的情况下清除终端的回滚缓冲区,然后重新绘制当前行,使当前行位于屏幕顶部。

clear-screen (C-l)

清除屏幕,然后重新绘制当前行,使当前行位于屏幕顶部。如果给出数字参数,则刷新当前行而不清除屏幕。

redraw-current-line ()

刷新当前行。默认情况下,此功能未绑定。

8.4.2 Commands For Manipulating The History

accept-line(换行或回车)

无论光标在哪里,都要接受这条线。如果该行非空,则根据 HISTCONTROL 和 HISTIGNORE 变量的设置将其添加到历史列表。如果此行是修改过的历史行,则恢复其原始状态。

previous-history(C-P)

在历史列表中"后退",获取上一个命令。这有时也绑定到某些键盘上的上箭头键。

next-history (C-n)

在历史列表中"前进",获取下一个命令。这有时也会绑定到某些键盘的下箭头键。

beginning-of-history (M-<)

历史起始(M-<)移动到历史的第一行。

end-of-history (M->)

移动到输入历史的末尾,即当前输入的行。

reverse-search-history (C-r)

从当前行开始向后搜索,并根据需要向"上"浏览历史记录。这是一种增量搜索。此命令会将区域设置为匹配的文本并激活该区域。

forward-search-history (C-s)

从当前行开始向前搜索,根据需要往下搜索历史。这是一个渐进式搜索。该命令将区域设置为匹配的文本并激活该区域。

non-incremental-reverse-search-history (M-p)

从当前行开始,按需向上搜索历史,使用用户提供的字符串进行非增量搜索。搜索字符串可以匹配历史行中的任意位置。

non-incremental-forward-search-history (M-n)

从当前行开始向前搜索,并根据需要使用用户提供的字符串进行非增量搜索,向历史"向下"搜索。搜索字符串可以匹配历史行中的任意位置。

history-search-backward()

在历史中回溯搜索当前行起点与点之间的字符串。搜索字符串必须在历史行开头匹配。这是一个非增量式搜索。默认情况下,该命令是未绑定的,但某些键盘可能会绑定到"Page Down"键。

history-search-forward ()

在历史中向前搜索当前行起点与点之间的字符串。搜索字符串必须在历史行开头匹配。这是一个非增量式搜索。默认情况下,该命令是未绑定的,但在某些键盘上可能会绑定到"翻页"键。

history-substring-search-backward ()

在历史中回溯搜索当前行起点与点之间的字符串。搜索字符串可以匹配历史行中的任意位置。这是一个非增量式搜索。默认情况下,该命令是未绑定的。

history-substring-search-forward ()

在历史中向前搜索当前行起点与点之间的字符串。搜索字符串可以匹配历史行中的任意位置。这是一个非增量式搜索。默认情况下,该命令是未绑定的。

yank-nth-arg (M-C-y)

在点处插入前一个命令的第一个参数(通常是前一行的第二个词)。参数n时插入前一个命令中的n个词(前一个命令中的词以词0开头)。负论元插入前一个命令结尾的第n个词。一旦计算出参数n,就使用历史扩展工具提取第n个词,就像"!n"历史扩展被指定一样。

yank-last-arg (M-. or M-_)

插入前一个命令的最后一个参数(上一个历史条目的最后一个词)。用数值参数,表现完全像 yank-nth-arg。连续调用 yank-last-arg 会返回历史列表,依次插入每行的最后一个字(或由第一个调用参数指定的字)。为这些连续调用提供的任何数值参数决定了历史进程的方向。否定论元则改变历史进程的方向(向前或向前)。这会利用历史扩展功能提取最终词,就像"!$"历史扩展被指定一样。

💡 yank-last-arg非常有用,我常用ESC+.调用。

operate-and-get-next (C-o)

接受当前行返回调用应用程序,就像输入了换行一样,并从历史中取出相对于当前行的下一行以便编辑。如果提供数值参数,则指定历史条目以代替当前行。

fetch-history ()

用数字参数,从历史列表中取出该条目,并将其设为当前行。没有争论,回到历史列表的第一条目。

8.4.3 Commands For Changing Text

end-of-file (usually C-d)

表示文件结束的字符,例如由stty设置。如果该字符在行中没有字符且光标位于行首时读取,Readline 将其解释为输入的结尾并返回 EOF。

bash 复制代码
$ stty -a|grep -oE "eof = [^;]*;"
eof = ^D;

$ cat > out
1
2
3
^D

delete-char (C-d)

删除光标上的字符。如果该函数与tty EOF特征绑定为同一字符,通常为C-d,效果请见上文。这有时也会绑定到某些键盘的Delete键上。

backward-delete-char (Rubout)

删除光标后面(左侧)的字符。数值参数意味着kill字符,将他们保存在剪贴环上,而不是删除。

即Backspace键。

bash 复制代码
$ stty -a|grep -oE " erase = [^;]*;"
 erase = ^?;

forward-backward-delete-char ()

删除光标下方的字符,除非光标位于行末,此时光标后方的字符被删除。默认情况下,这不会绑定在按键上。

quoted-insert (C-q or C-v)

将下一个输入的字符逐字添加到行中。比如插入像C-q这样的按键序列。

self-insert (a, b, A, 1, !, ...)

插入输入的字符。

bracketed-paste-begin ()

该函数旨在绑定到某些终端发送的"括号粘贴"转义序列,默认会赋予此类绑定。它允许 Readline 将粘贴的文本作为一个单元插入,而不把每个字符当作从键盘读取的字符处理。字符插入时仿佛每个字符都绑定为自我插入,而不是执行任何编辑命令。

括号粘贴将区域(点与标记之间的字符)设置为插入文本。它会设定活跃区域。

transpose-chars (C-t)

将光标前的字符向前拖拽到光标位置的字符上,同时将光标也向前移动。如果插入点位于行末,则将行的最后两个字符置换。负值参数无效。

transpose-words (M-t)

将光标前的单词拖到插入点后的单词之后,同时将光标也移动到该单词之后。如果光标在行尾,这将交换该行的最后两个单词。

shell-transpose-words (M-C-t)

将光标前的单词拖到光标后的单词之后,同时将光标也移动到该单词之后。如果插入点位于行尾,这将交换该行最后两个单词。单词边界与 shell-forward-word 和 shell-backward-word 相同。

upcase-word (M-u)

将当前(或下一个)单词转换为大写字母。使用负数参数时,将上一个单词转换为大写,但不要移动光标。

💡 所谓使用负数参数,就是先按M--

downcase-word (M-l)

将当前(或下一个)单词转换为小写字母。使用负数参数时,将上一个单词转换为小写,但不要移动光标。

capitalize-word (M-c)

将当前(或下一个)单词首字母大写。使用负数参数时,将前一个单词首字母大写,但不要移动光标。

overwrite-mode ()

切换覆盖模式。使用明确的正数参数时,切换到覆盖模式。使用明确的非正数参数时,切换到插入模式。此命令仅影响 emacs 模式;vi 模式下的覆盖操作方式不同。每次调用 readline() 时都从插入模式开始。

在覆盖模式中,绑定到 self-insert 的字符会替换光标处的文本,而不是将文本向右推。绑定到 backward-delete-char 的字符会将光标前的字符替换为空格。

默认情况下,此命令未绑定,但在某些键盘上可能会绑定到插入键。

8.4.4 Killing And Yanking

💡 kill and yank 类似于 cut and paste

kill-line (C-k)

删除从光标位置到当前行末尾的文本。若带负数参数,则从光标向后删除至行首。

backward-kill-line (C-x Rubout)

从光标向后删除至当前行首。若带负数参数,则从光标向前删除至行尾。

unix-line-discard (C-u)

从光标向后删除至当前行开头。

kill-whole-line ()

删除当前行所有字符,无论光标位置。默认未绑定。

kill-word (M-d)

删除从光标到当前单词末尾的文本,若位于单词间则删除至下个单词末尾。单词边界与forward-word相同。

backward-kill-word (M-DEL)

删除光标后方的单词。单词边界与backward-word相同。

shell-kill-word (M-C-d)

删除光标至当前单词末尾,若位于单词间则删除至下个单词末尾。单词边界与shell-forward-word相同。

shell-backward-kill-word ()

删除光标后方单词。单词边界规则与shell-backward-word相同。

unix-word-rubout (C-w)

删除光标后方(左侧)单词,以空格作为单词边界,并将删除内容保存至剪贴环。

unix-filename-rubout ()

删除光标后方单词,以空格和斜杠字符作为分隔符,并将删除内容保存至剪贴环。

delete-horizontal-space ()

删除光标周围所有空格与制表符。默认未绑定此命令

kill-region ()

删除当前区域内的文本。默认情况下,此命令未绑定。

copy-region-as-kill ()

将区域内的文本复制到剪贴环,以便立即粘贴。默认情况下,此命令未绑定。

copy-backward-word ()

将光标前方的单词复制到剪贴环。单词边界与 backward-word 相同。默认未绑定。

copy-forward-word ()

将光标后方的单词复制到剪贴环。单词边界与 forward-word 相同。默认未绑定。

yank (C-y)

将剪贴环顶部内容粘贴至光标所在缓冲区。

yank-pop (M-y)

轮换剪贴环内容,并粘贴新顶部内容。仅当前次操作为 yank 或 yank-pop 时可用。

8.4.5 Specifying Numeric Arguments

digit-argument (M-0, M-1, ... M--)

将此数字添加至正在累加的参数,或启动新参数。M-- 启动负参数。

universal-argument ()

此为指定参数的另一种方式。若该命令后跟一个或多个数字(可选带前导负号),则这些数字定义参数。若命令后跟数字,再次执行通用参数将结束数字参数,否则该命令将被忽略。特殊情况:若该命令后紧跟非数字非负号的字符,则下条命令的参数计数将乘以四。参数计数初始值为一,首次执行此函数使计数变为四,第二次变为十六,依此类推。默认情况下此功能未绑定快捷键。

8.4.6 Letting Readline Type For You

complete (TAB)

尝试对光标前方的文本执行补全操作。实际执行的补全操作取决于具体应用程序。Bash 首先检查命令词是否存在可编程补全(参见可编程补全),否则依次将文本视为变量(若以'$'开头)、用户名(若以'~'开头)、主机名(若以'@'开头)或命令(包括别名、函数和内置命令)。若上述均未匹配,则回退至文件名补全。

possible-completions (M-?)

列出光标前文本的可能补全项。显示补全项时,Readline依次采用以下值设定显示列数:completion-display-width 环境变量值、COLUMNS 环境变量值或屏幕宽度。

bash 复制代码
$ cd /usr/include
$ ls c<此处按(M-?)键>
complex.h  cpio.h     cpuidle.h  crypt.h    ctype.h
$ ls c

insert-completions (M-*)

将光标前文本的所有补全项(即可能补全功能所生成的补全项)插入,各补全项间以空格分隔。

bash 复制代码
$ ls c<此处按(M-*)键>
complex.h  cpio.h     cpuidle.h  crypt.h    ctype.h
$ ls complex.h cpio.h cpuidle.h crypt.h ctype.h

menu-complete ()

类似于complete命令,但会将待补全的单词替换为补全候选列表中的某个匹配项。重复执行menu-complete将遍历补全候选列表,依次插入每个匹配项。当遍历至补全候选列表末尾时,menu-complete会发出提示音(具体音效取决于bell-style设置)并恢复原始文本。传入参数n可在匹配项列表中向前移动n个位置;负参数则向后移动。本命令默认未绑定,建议绑定至TAB键。

menu-complete-backward ()

与menu-complete功能相同,但向后遍历可能的补全项列表,效果等同于menu-complete接收负参数。本命令默认未绑定。

export-completions ()

对光标前方的单词执行上述补全操作,并将可能的补全结果列表按以下格式写入Readline的输出流,每行单独输出信息:

  • 匹配项数量 N;
  • 待补全的单词;
  • S:E,其中S和E分别是该单词在Readline行缓冲区中的起始偏移量和结束偏移量;然后
  • 每行输出一个匹配项

若无匹配项,首行将显示"0",且本命令在S:E之后不输出任何内容。若仅存在单一匹配项,则输出包含该项的单行。若存在多个匹配项,则在S:E后的首行输出匹配项的公共前缀(可能为空),随后各行输出具体匹配项。此时N将包含首行公共前缀。

用户或应用程序需能处理空行情况。其设计意图是让用户或应用程序在读取包含S:E的行之后,继续读取N行以获取匹配列表。该命令默认未绑定。

delete-char-or-list ()

删除光标下的字符(除非位于行首或行尾,类似 delete-char)。在行尾时,其行为与 possible-completions 完全相同。此命令默认未绑定。

complete-filename (M-/)

对光标前文本尝试文件名补全。

possible-filename-completions (C-x /)

将光标前文本视为文件名,列出其可能的补全项。

complete-username (M-~)

将光标前文本视为用户名,尝试进行补全。

possible-username-completions (C-x ~)

将光标前文本视为用户名,列出其可能的补全项。

complete-variable (M-$)

尝试对光标前文本进行补全,将其视为 shell 变量。

possible-variable-completions (C-x $)

列出光标前文本的可能补全项,将其视为 shell 变量。

complete-hostname (M-@)

尝试对光标前文本进行补全,将其视为主机名。

possible-hostname-completions (C-x @)

列出光标前文本的可能补全项,将其视为主机名。

complete-command (M-!)

尝试补全光标前文本,将其视为命令名称。命令补全按以下顺序匹配文本:别名、保留字、shell函数、shell内置命令,最后是可执行文件名。

possible-command-completions (C-x !)

列出光标前文本的可能补全项,将其视为命令名称。

dynamic-complete-history (M-TAB)

尝试对光标前文本进行补全,将文本与历史记录条目进行比对以查找可能的补全匹配项。

dabbrev-expand ()

尝试对光标前文本进行菜单补全,将文本与历史记录列表中的行进行比对以寻找可能的补全匹配项。

complete-into-braces (M-{)

执行文件名补全,并将可能的补全项列表用大括号括起后插入,以便在shell中使用(参见大括号展开)。

bash 复制代码
$ ls c*
complex.h  cpio.h  cpuidle.h  crypt.h  ctype.h

$ ls c<此处按(M-{)键>
$ ls c{omplex.h,p{io.h,uidle.h},rypt.h,type.h}
$ echo c{omplex.h,p{io.h,uidle.h},rypt.h,type.h}
complex.h cpio.h cpuidle.h crypt.h ctype.h

8.4.7 Keyboard Macros

start-kbd-macro (C-x ())

开始保存当前键盘宏中输入的字符。

end-kbd-macro (C-x ))

停止保存当前键盘宏中输入的字符并保存定义。

call-last-kbd-macro (C-x e)

重新执行最后定义的键盘宏,使宏中的字符如同在键盘上输入般生效。

print-last-kbd-macro ()

以适合输入配置文件的格式打印最后定义的键盘宏。

8.4.8 Some Miscellaneous Commands

re-read-init-file (C-x C-r)

读取输入配置文件的内容,并整合其中发现的任何键绑定或变量赋值。

abort (C-g)

中止当前编辑命令并触发终端蜂鸣器(受bell-style设置影响)。

do-lowercase-version (M-A, M-B, M-x, ...)

若元化字符 x 为大写,则执行绑定至对应小写元化字符的命令。若 x 本身已是小写,则行为未定义。

prefix-meta (ESC)

对下一个输入字符进行元操作。输入'ESC f'等同于输入M-f。

undo (C-_ or C-x C-u)

逐行增量撤销,每行操作独立保存。

revert-line (M-r)

撤销本行所有修改。相当于重复执行撤销命令直至恢复初始状态。

tilde-expand (M-&)

对当前单词执行波浪号扩展。

set-mark (C-@)

将标记设置为光标位置。若提供数字参数,则将标记设置至该位置。

exchange-point-and-mark (C-x C-x)

交换光标点与标记位置。将当前光标位置设为保存位置,并将标记设为原光标位置。

character-search (C-])

读取一个字符,并将光标移至该字符的下一个出现位置。负参数表示搜索前一个出现位置。

character-search-backward (M-C-])

读取字符并将光标移至该字符的前一个出现位置。负参数表示搜索后续出现位置。

skip-csi-sequence ()

读取足够字符以消耗多键序列(如Home/End键定义的序列)。CSI序列以控制序列指示符(CSI)开头,通常为ESC [。若该序列绑定为"\e[",则产生CSI序列的按键将失效(除非显式绑定至Readline命令),避免向编辑缓冲区插入异常字符。默认未绑定,但通常绑定至ESC [。

insert-comment (M-#)

若未提供数字参数,则在当前行开头插入注释开始变量的值。若提供数字参数,则该命令作为切换操作:若行首字符与注释开始变量的值不匹配,则插入该值;否则从行首删除注释开始变量中的字符。无论哪种情况,该行均被视为已输入换行符。默认的comment-begin值会使当前行成为shell注释行。若数值参数导致注释字符被移除,则该行将被shell执行。

dump-functions ()

将所有函数及其键绑定打印至Readline输出流。若提供数字参数,输出将采用可直接纳入输入配置文件的格式。此命令默认未绑定。

dump-variables ()

将所有可设置变量及其值打印至Readline输出流。若提供数字参数,输出将采用可直接纳入输入配置文件的格式。该命令默认未绑定。

dump-macros ()

将所有绑定到宏的Readline键序列及其输出字符串打印到Readline输出流。若提供数字参数,则输出将按可纳入inputrc文件的格式呈现。该命令默认未绑定。

execute-named-command (M-x)

从输入中读取可绑定Readline命令名称,并执行其绑定的函数,如同输入中出现了该命令绑定的键序列。若该函数接收数字参数,则将该参数传递给执行的函数。

spell-correct-word (C-x s)

对当前单词执行拼写校正,将其视为目录或文件名,操作方式与cdspell shell选项相同。单词边界与shell-forward-word使用的边界一致。

glob-complete-word (M-g)

将光标前单词视为路径名扩展模式(隐含附加星号),据此生成匹配文件名的补全候选列表。

glob-expand-word (C-x *)

将光标前单词视为路径名扩展模式,插入匹配文件名列表并替换原单词。若提供数字参数,则在路径名扩展前附加'*'。

glob-list-expansions (C-x g)

显示glob-expand-word本应生成的扩展列表,并重新显示当前行。若提供数字参数,则在路径名扩展前附加'*'。

下例解释"在路径名扩展前附加'*'":

bash 复制代码
$ ls /etc/passwd*
/etc/passwd  /etc/passwd-
$ ls /etc/passwd<C-x g>
passwd
# 带数字参数后,相当于ls /etc/passwd*
$ ls /etc/passwd<M-1><C-x g>
passwd   passwd-

shell-expand-line (M-C-e)

通过执行shell单词扩展来扩展当前行。此操作包含别名和历史扩展、$'string'$"string"引号处理、波浪号扩展、参数和变量扩展、算术扩展、命令和进程替换、单词分割以及引号移除。显式参数可抑制命令和进程替换。

history-expand-line (M-^)

对当前行执行历史扩展。

magic-space ()

对当前行执行历史扩展并插入空格(参见历史扩展)。

alias-expand-line ()

对当前行执行别名扩展(参见别名)。

history-and-alias-expand-line ()

对当前行执行历史扩展和别名扩展。

insert-last-argument (M-. 或 M-_)

yank-last-arg 的同义命令。

edit-and-execute-command (C-x C-e)

在当前命令行调用编辑器,并将结果作为shell命令执行。Bash将按顺序尝试调用VISUAL、EDITOR和emacs作为编辑器。

bash 复制代码
$ echo $VISUAL $EDITOR

$ C-x C-e
-bash: emacs: command not found
$ EDITOR=vi
$ C-x C-e
# 进入vi编辑器

display-shell-version (C-x C-v)

显示当前Bash实例的版本信息。

bash 复制代码
$ C-x C-v
GNU bash, version 5.1.8(1)-release (x86_64-redhat-linux-gnu)

8.5 Readline vi Mode

虽然Readline库不具备完整的vi编辑功能,但其提供的功能足以实现对行内容的简单编辑。Readline的vi模式行为符合POSIX标准中sh描述的规范。

可通过'set -o emacs'和'set -o vi'命令(参见内置命令set)在emacs与vi编辑模式间交互切换,Readline默认启用emacs模式

在 vi 模式下输入行时,系统默认处于'插入'模式,如同已输入'i'键。按下 ESC 键可切换至'命令'模式,此时可使用标准 vi 移动键编辑行内文本,通过'k'键回溯历史行,'j'键前进至后续行,等等。

💡 熟悉vi的话,vi的行编辑确实也挺好用的。一些按键绑定如C-r仍可用,不过有些就有冲突了,如C-p在emacs模式下为上一条命令,在vi模式下则为自动补全,但可以用向上键代替。

相关推荐
香芋Yu2 小时前
【从零构建AI Code终端系统】02 -- Bash 工具:一切能力的基础
开发语言·bash·agent·claude
dingdingfish11 小时前
Bash学习 - 第7章:Job Control
bash·shell·wait·job
dingdingfish17 小时前
Bash学习 - 第8章:Command Line Editing,第1-2节:Intro & Readline Interaction
bash·shell·readline
dingdingfish2 天前
Bash学习 - 第6章:Bash Features,第11节:Bash and POSIX
bash·posix
dingdingfish2 天前
Bash学习 - 第6章:Bash Features,第12节:Shell Compatibility Mode
bash·shell·compat·compatibility
dingdingfish3 天前
Bash学习 - 第6章:Bash Features,第9节:Controlling the Prompt
prompt·bash·ps1
dingdingfish3 天前
Bash学习 - 第6章:Bash Features,第10节:The Restricted Shell
bash·shell·rbash·restrict
数形长夏3 天前
命令行界面的神秘符号,是上一代程序复用的尝试
架构·bash·batch
dingdingfish4 天前
Bash学习 - 第6章:Bash Features,第7节:Arrays
bash·shell·array·index·associate