8.bash编辑命令行

8.编辑命令行
本章介绍 GNU 命令行编辑界面的基本功能。
命令行编辑是 Readline 库提供的;这个库被几个不同的程序共用,Bash 是其中一个。
使用交互式的 shell 时,默认已经打开了命令行编辑,除非启动 shell 时指定 了"--noediting"选项。
当使用内部命令 read 的"-e"选项时也会使用行编辑。
默认情况下,行编辑命令和 emacs 的很相似;但也可以使用 vi 风格的行编辑界面。
在任何时候,都可以使用内部命令 set 的"-o emacs"或"-o vi"选项来打开行编辑, 或者使用 set 的"+o emacs"或"+o vi"选项来关闭。

8.1 行编辑介绍
下面几段介绍键的表示方法。
字符 C-k 读作"Control-K",它表示按下 Control 键时再按 k 键所得到的字符。
符号 M-k 读 作"Meta-K",它表示按下 Meta 键 (如果有这个键)时再按 k 键所得到的字符。
在很多键盘上, Meta键都标上 ALT 。
如果一个键盘有两个标为 ALT 的键 (通常在空格键的两旁),则一般左边的那个可以当Meta 键使用。
右边的那个 ALT 键也可以配置成 Meta 键,或者配置成其它的修饰键,例如用来输入字 母音符的 Compose 键。
如果没有 Meta 或 ALT 键,也没有其它可以当成 Meta 键的,则可以先按下 ESC 再按下 k 来得到同样的键。
这两种键都叫 Meta 化的 k 键。
字符 M-C-k 读作"Meta-Control-K",它表示Meta化的 C-k 。
此外,还有几个键有独特的名称。特别的,本文或初始化文件中出现的 DEL 、 ESC 、 LFD 、 SPC 、 RET 和 TAB 都表示其自身。
如果键盘上没有 LFD 键,输入C-j 也会得到同样的字符。
在有些键盘上, RET 键可能被标为 Return 或 Enter 键。

8.2 与Readline的交互
在交互式的会话中,常常是输入了很长的一行文本,却发现这行的第一个单词拼写错了。
Readline 提供了一套在输入时控制文本的命令,用来改正输入错误,而不必要重新输入大部分内容。
使用这些编辑命令,可以把光标移动到需要更正的地方,删除或者插入更正的内容;然后,如果文本行还令人满意,就按下RET 。
按下 RET 不一定要在行的结尾;整行都会读入,不管光标在行中的什么地方。

8.2.1 Readline的基础
要在行中输入字符,只韪要按下对应的键。
输入的字符在光标后出现,然后光标就向后移动一格的位置。
如果输错了一个字符,可以用删除字符后退并删除这个输错的字符。
有时,输错了不会马上发现,直到又输入了好个几个字符。
这种情况下,可以输入 C-b 向左移动光标然后更正错误。
接下来,可以用 C-f向右移动光标。
如果在行的中间输入,就会发现光标右边的字符被"推过去"以腾出空间容纳刚刚输入的文本。
同样的, 删除光标下的字符时,光标右边的字符也会被"推过来"以填入删除后留出的空白中。
下面是编辑输入文本行 用到的构基础的命令:
C-b 向后移动一个字符的位置。
C-f 向后移动一个字符的位置。
DEL 或 Backspace 删除光标左边的字符。
C-d 删除光标下面的字符。
可打印字符 在光标处插入该字符。
C- 或 C-x C-u 取消最后一次输入命令。可以一直取消直到行为空。
(取决于配置, Backspace 可以设为删除光标左边的字符,而 DEL 设为和 C-d 一样删除光标下面的字符,而不是其左边的。)

8.2.2 Readline的移动命令
上面列出了编辑输入行时要用到的最基本的键。
为了方便,除了 C-b 、 C-f 、 C-d 、 DEL 以外, 还有其它编辑命令。
下面这些命令可以用来在行内部快速移动。
C-a 移到行的径头。
C-e 移到行的结尾。
M-f 向前移动一个单词的位置 ;单词是由字母和数字构成的。
M-b 向后移动一个单词的位置。
C-l 清除屏幕,然后在顶端打印当前行。
注意:C-f 向前移动一个字符,而 M-f 向前移动一个单词。有个很松散的习惯,就是 Control 键操纵字符而Meta 键操纵单词。

8.2.3 Readline的删除命令
删除"kill"是指把文本从行中移除并保存下来以备后用,通常是后来重新插入"yank"到行中(现在常说"剪切"和"复制")。
如果介绍命令时说它"删除"文本,则可以保证在另外一个地方恢复这些文本。
使用删除命令时,文本被放在删除环中。
后面连续删除的文本也会被放在一起,所以重新插入时,会一下子恢复所有文本。
删除环不是针对行的;在前面一行删除的文本可以在以后输入另外一行时恢复。
下面的命令用来删除文本。
C-k 从当前光标的位置删除到行的结尾。
M-d 从光标的位置删除到当前单词的结尾;如果是在单词之间,则删除到下一个单词的结尾。单词界限和 M-f 所使用的一样。
M-DEL 从光标删除到当前单词的径头;如果是在单词之间,则删除到止上个单词的开头。单词界限和M-b 所使用的一样。
C-w 从光标删除到上一个空白符。这和 M-DEL 使用的单词界限是不一样的。
下面这些命令用来在行中恢复文本。重新插入是指从删除缓存中复制最后被删除的文本。
C-y 把最近删除的文本插入到光标所在的缓存中。
M-y 循环到删除环,并插入新的顶端文本。只有当前一个命令是 C-y 或者 M-y 时才可以用这个命令。

8.2.4 Readline的参数
Readline 命令可以接受数值型参数。有时这些参数可以表示重复次数,有时数值的正负符号很重要。
如果一个通常向前进行的命令得到了一个负的参数,则它会向后进行。
例如,删除到行开头的文本,可以使用" M-- C-k "。
给命令指定参数的一般方法是在命令前面输入 Meta 化的数字。
如果输入的第一个"数位"是负号" - ",则这个参数将是负数。
开始输入了参数的第一个 Meta 化的数字后,就可以输入其余数字,然后再输入命令。
例如,给 C-d 命令以参数 10,则可以输入" M-1 0 C-d ",这会删除输入行中后面十个字符。

8.2.5 在历史中搜索命令
Readline 提供的可以搜索历史的命令以寻找包含指定字符串的行。 搜索命令有两种,增量的和非增量的。
增量搜索在用户输入搜索字符串结束前就弱始搜索。第输入字符串的一个字符时,Readline 都会显示历史中与已经输入的字符串匹配的行。
增量搜索时,实际需要输入多少字符就输入多少,就能找到想要的历史。
在历史中向后搜索包含特定字符串的行可以用 C-r ;而 C-s 表示向前搜索。
isearch-terminators变量中的字符可以用来结束增量搜索。如果这个变量没有设置值,就用 ESC 或 C-j 来结束增量搜索。
C-g 可以退出增量搜索并恢复之前的行。搜索结束以后,历史中包含搜索字符串的行就成为当前行。
如果要在历史中搜索其它匹配的行,可以根据靮要再输入 C-r 或 C-s ;这会在历史中向前或向后搜 索与已经输入的搜索字符串匹配的下一行。
与 Readline 命令绑定的任何其它键序列都会结束搜索并执行搜索到的命令。
例如, RET 会结束搜索并提交一整行,所以会执行历史中的对应命令。
移动命令也会结束搜索,并把最后找到的行作为当前行后弎始编辑。
Readline 会记住最后一次增量搜索的字符串。如果输入的两个 C-r 之间没有其它搜索字符串,就会使用已经记住的字符串。
非增量搜索在开始搜索匹配的历史行之前要读取整个搜索字符串。搜索字符串可以由用户输入,也可以是当前行的部分内容。

8.3 Readline的启动脚本
虽然 Readline 库默认安装了一套 eamcs 风格的键绑定,使用其它的键绑定也是可以的。
任何用户都可以在一个 inputrc 文件中放入 Readline 命令来对使用 Readline 的程序进行自定义;这个文件通常在用户的主目录内。
文件的名称来自 shell 变量 INPUTRC 的值。
如果这个变量没有设置,则使用默认 的"~/.inputrc";如果这个文件不存在或者不可读取,则最终的默认值是"/etc/inputrc"。
一个使用 Readline 库的程序在启动时会读取初始化文件并绑定键。此外, C-x C-r 会重新读入初始化文件,所以会使任何改动生效。

8.3.1 Readline启动脚本的语法
Readline 的初始化文件里面只能使用一些基本的结构。
空行会被忽略掉。以"#"开头的行是注释。 以"$"开头的行表示条件结构。其它行表示变量赋值和键绑定。

8.3.1.1 变量赋值
可以用在初始化脚本中用 Readline 的 set 命令修改变量的值来改变 Readline 的运行时行为。
其语法很简单:set 变量 值
例如,下面就示范了怎么把默认的 eamcs 风格键绑定改成使用 vi 风格的行编辑命令:set editing-mode vi
在解析变量的名称和值时会根据情况忽略大小写。不能识别的变量会被忽略。
对于布尔型的变量(即可以打开或关闭的),如果其值没有设置、或者为空、或者是 on (不区分大小写)、或者是 1,就会打开。
任何其它值都会关闭这个变量。
命令 bind -V 可以列出当前的 Readline 变量和值 。
大量的运行时行为都可以由下列变量来更改。
bell-style 控制 Readline 想让终端铃声响起时发生的动作。如果设为 none,则不响铃;如果设为visible,则如果有可见响铃就使用可见响铃;如果设为 audible(默认的),Readline 会试图让终端的铃声响起。助记词: 响铃方式
bind-tty-special-chars 如果设为 on,Readline 会试图把内核的终端驱动程序要特殊处理的字符映射到自己对应的字符上。助记词: 绑定终端特殊字符
comment-begin 在执行 insert-comment 命令时要插入行开头的字符;默认值是"#"。助记词: 注释开始
completion-ignore-case 如果设为 on,Readline 在进行文件名匹配和补全时会忽略大小写。默认值是off。助记词: 忽略补全大小写
completion-prefix-display-length 补全列表中不加修改而直接显示的公共前缀的字符长度。
如果设为大于零的值,则比这个值大的公共前缀将会在列出补全时被替换成省略号。助记词: 补全前缀显示长度
completion-query-items 决定询问用户是否需要显示补全列表时补全列表的长度。
如果补全列表的长度大于这个值,Readline 会询问用户是否想查看;否则,就直接显示列表。
这个变量必须设置一个大于或等于0的整数。负值表示 Readline 不会询问。默认值是 100。助记词: 补全询问长度
convert-meta 如果设为 on,Readline 会把设置了高八位的字符的第八位(最高位)去掉并加上一个前导的ESC字符,从而把它们转换成Meta化的ASCII字符序列。默认值是 on。助记词: Meta 转换
disable-completion 如果设为 on,Readline 将不会补全单词。补全字符会被插入行中,就好像这些字符也绑定了 self-insert 命令。默认值是 off。助记词: 禁用补全
editing-mode 这个变量控制默认使用哪种键绑定。默认情况下,Readline启动emacs风格的编辑模式,其中的键很像emacs。这个变量可以被设为emacs或vi。助记词: 编辑模式
enable-keypad 如果设为 on,Readline 在启动时启用小键盘。有些系统依赖小键盘上的方向键。默认 值是 off。助记词: 启用小键盘
expand-tilde 如果设为 on,Readline 在试图对单词进行补全时要进行波浪号扩展。默认值是 off。助记词: 扩展波浪号
history-preserve-point 如果设为 on,则对于通过 previous-history 或 next-history 得到的每个历史行,标志点(光标的当前位置)将会停留在行中同样的地方。默认值是 off。助记词: 保持历史标志点
history-size 历史列表中所保存的历史行的最大数目。如果设为零,则历史列表中保存的历史行不受限制。助记词: 历史长度
horizontal-scroll-mode 可以设为 on 或 off。如果设为 on,则如果正在编辑的行比屏幕宽,就会在单行内水平滚动,而不是开始新行。默认值是 off。助记词: 水平滚动模式
input-meta 如果设为 on,Readline 会启用八位字符的输入(即不会清除每个所读入字符的第八位),不管终端支持与否。默认值是 off。meta-flag 和它是同义的。助记词: Meta 输入
isearch-terminators 结束增量搜索而不会把字符当作命令去执行的一个字符串。如果没有设置这个变量,则 ESC 和 C-j 字符会结束增量搜索。助记词: 增量搜索 结束符
keymap 设置 Readline 当前用来绑定命令的键映射。可用的键映射有 emacs、emacs-standard、emacs-meta、emacs-ctlx、vi、vi-move、vi-command、vi-insert。
其中,vi 和 vi-command 是等价的,emacs和 emacs-standard 也是等价的。默认值是 emacs。editing-mode 变量的值也会影响默认的键映射。 助记词: 键映射
mark-directories 如果设为 on,在补全后的目录后面加上斜杠。默认值是 off。助记词: 标志出目录
mark-modified-lines 如果设为 on,Readline 将会在已被修改的历史行开头显示一个星号("*")。默 认值是 off。助记词: 标志已修改的行
mark-symlinked-directories 如果设为 on,并且补全后的名称是个指向目录的符号链接,则在后面加上斜杠(还要看 mark-directories 的值)。默认值是 off。助记词: 标志目录的符号链接
match-hidden-files 如果设为 on,Readline 在补全文件名时会匹配以"."开头的文件 (即隐藏文件),除非用户在要补全的文件名开头指定了"."。默认值是 on。助记词: 匹配隐藏文件
output-meta 如果设为 on,Readline 会直接显示设置了高八位的字符,而不是显示 Meta 化的序列。 默认值是 off。助记词: Meta 输出
page-completions 如果设为 on,Readline 会使用其内部类似于 more 命令的分页程序来显示一次性满屏的补全。默认值是 on。助记词: 补全分页
print-completions-horizontally 如果设为 on,Readline 会把匹配的补全条目按字母顺序排列并水平显示,而不是在屏幕中垂直显示。默认值是 off。助记词: 水平显示补全
revert-all-at-newline 如果设为 on,Readline 会在执行 accept-line 时恢复历史行的所有改动。默认情况下,改动过的历史行在多次使时可以各自恢复。默认值是 off。助记词: 提交时恢复所有历史
show-all-if-ambiguous 这会改变补全命令的默认行为。如果设为 on,则如一个单词有多个匹配将会立即被全部列出,而不是响铃。默认值是 off。助记词: 如有岐义就显示全部
show-all-if-unmodified 这会以类似于 show-all-if-ambiguous 的方式改变补全命令的默认行为。
如果设为 on,则如一个单词有多个匹配,并且它们都不是部分匹配(即匹配的条目不含有公共前缀)将会立即被全部列出,而不是响铃。默认值是 off。助记词: 如未修改则显示全部
visible-stats 如果设为 on,则在列出补全条目时在文件名后面加上一个用以显示其类别的字符。默 认值是 off。助记词: 可见的类型

8.3.1.2 键绑定
初始化文件中控制键绑定的语法是很简单的。
首先要找到需要使用的命令名。下面各节中有命令名的列表,以及命令功能的简单描述;如果有键绑定,也一并列出。
知道了命令名称以后,只要在初始化文件的某一行中写入要和该命令绑定的键,后面加个冒号,然后再写上这个命令就可以了。
在键名和冒号之间不可以有空格,否则这些空格也会成为键名的一部分。
键名可以有不同的表示方法,自己看着舒服的那种就行。
除了可以绑定命令名称,Readline 还允许绑定一个字符串,这样键入绑定的键名(宏)后就能插入这个字符串。
bind -p 命令可以输出 Readline 中的命令和绑定;输出的格式可以直接放在初始化文件中 。
键名:命令名或宏 键名是英语中一个键的名称。
例子:
Control-u: universal-argument C-u 绑定到了 universal-argument 命令
Meta-Rubout: backward-kill-word M-DEL 绑定到了 backward-kill-word命令
Control-o: "> output" C-o 绑定可以运行其右边所写的宏(即把文本"> output"插入到行中)
在处理绑定时可以使用一些键符号:DEL、ESC、ESCAPE、LFD、NEWLINE、RET、RETURN、RUBOUT、SPACE、SPC以及TAB。
键序列:命令名或宏 键序列和上面的键名不同之处在于它可以把键名序列放在双引号中间的字符串来表示整个键序列。
可以使用 emacs 风格的转义键名,但不能使用特殊的键名。
例子:
"\\C-u": universal-argument C-u 仍绑定了 universal-argument 命令
"\\C-x\\C-r": re-read-init-file C-x C-r 绑定了re-read-init-file 命令
"\\e[11~": "Function Key 1" ESC [11 ~ 绑定了插入文本"Function Key 1"
指定键序列时可以使用下列 emacs 风格的转义序列:
\C- 控制键前缀。
\M- Meta前缀。
\e 一个转义字符。
\\ 反斜杠。
\” 双引号。
\fl 单引号或省字符。
除了 emacs 风格的转义序列,还可以用另外一套转义序列:
\a 警告(响铃)
\b 退格删除
\d 删除
\f 走纸换页
\n 新行
\r 换行
\t (水平)制表符
\v 垂直制表符
\nn 由八进制数 nnn(一个到三个数字)代表的一个八位字符。
\xHH 由十六进制数 HH(一个或两个十六进制数字)代表的一个八位字符。
在宏中写入文本时必须用单引号或双引号表示宏定义。没有引用的文本会被当成命令名称。
在宏里面,上面列出的转义字符会被扩展。反斜杠可以转义后面的任意字符,包括"""和"'"。
例如,下面的绑定会使用 C-x \\ 能够在行中输入"\": "\C-x\\: "\\"

8.3.2 Readline启动脚本的条件结构
Readline 实现了与C语言预编译器中的条件编译很神似的功能,它使得键绑定和变量赋值根据测试结果进行。
它使用了四种方法指示解释器。
$if 这种结构根据编辑模式,所有终端或使用 Readline 的程序进行绑定。测试所用的文本一直延伸到行的结尾,不需要字符去隔离它。
mode mode= 形式的 $if 指令用来测试 Readline 使用的模式是 emacs 还是 vi。
例如,它可以和"set键映射"命令一起使用,使 Readline 只有在 emacs 模式中才绑定 emacs-standard 和 emacs-ctlx的键。
term term= 的形式可以用来绑定与终端相关联的键,例如绑定终端功能键的输出。
"="右边的单词用来和终端的完整名称以及名称中第一个"-"前面的部分进行匹配。例如,sun会与sun和sun-cmd匹配。
application 这种结构用来包含与应用程序相关联的设置。
每个使用 Readline 库的程序都会设置程序名称,这个名称可以用于测试,并用来绑定只针对特定程序的键序列。
例如,下面的命令在Bash中加入了一个键绑定用来给当前和前一个单词加引号:
$if Bash
# Quote the current or previous word
"\C-xq": "\eb\"\ef\""
$endif
$endif 用来结束 $if 命令。
$else $if 结构的分支,当 $if 测试失败时执行。
$include 这个结构带一个文件名参数并从文件中读取和执行命令。
例如,下面的命令读取"/etc/inputrc": $include /etc/inputrc

8.3.3 Readline启动脚本的例子
下面是 inputrc 文件的一个实例。它示范了键绑定,变量赋值和条件语法。
代码清单6:Readline 启动脚本的例子
# vim:filetype=readline
# 本文件控制所有使用 readline 库的程序的行输入行为。
# 这些程序包括 FTP,Bash 和 GDB。
# 可以用 C-x C-r 命令重新加载该文件。
# 以 '#' 开头的行是注释。
# 首先,包含 /etc/Inputrc 中的任何系统绑定和变量。
$include /etc/Inputrc
# 设置 emacs 风格的绑定。
set editing-mode emacs
$if mode=emacs
Meta-Control-h: backward-kill-word 命令后面的文本会被忽略掉
# 小键盘上的方向键
#"\M-OD": backward-char
#"\M-OC": forward-char
#"\M-OA": previous-history
#"\M-OB": next-history
# ANSI 模式的方向键
"\M-[D": backward-char
"\M-[C": forward-char
"\M-[A": previous-history
"\M-[B": next-history
# 八位小键盘上的方向键
#"\M-\C-OD": backward-char
#"\M-\C-OC": forward-char
#"\M-\C-OA": previous-history
#"\M-\C-OB": next-history
# 八位 ANSI 模式的方向键
#"\M-\C-[D": backward-char
#"\M-\C-[C": forward-char
#"\M-\C-[A": previous-history
#"\M-\C-[B": next-history
C-q: quoted-insert
$endif
# 旧式的绑定。这恰好也是默认的。
TAB: complete
# 便于 shell 交互的宏。
$if Bash
# 编辑 PATH 路径
"\C-xp": "PATH=${PATH}\e\C-e\C-a\ef\C-f"
# 准备输入引用的单词:插入引号的径始和结束,然后移到弰始引号的后面。
"\C-x\"": "\"\"\C-b"
# 插入反斜杠(测试反斜杠转义序列和宏)。
"\C-x\": "\"
# 用引号引用当前或前一个单词。
"\C-xq": "\eb\"\ef\""
# 绑定刷新本行的命令;这原来是没有绑定的。
"\C-xr": redraw-current-line
# 编辑本行中的变量。
"\M-\C-v": "\C-a\C-k$\C-y\M-\C-e\C-a\C-y="
$endif
# 如果可以响铃就使用
set bell-style visible
# 读取输入时不要把字符截成 7 位。
set input-meta on
# 允许插入 iso-latin1 字符,而不是把它们变成 Meta 化的序列。
set convert-meta off
# 直接显示八位的字符,而不是把它们当成 Meta 化的字符来显示。
set output-meta on
# 如果可以补全的项目超过 150 条,询问用户是否要显示全部。
set completion-query-items 150
# 用于 FTP
$if Ftp
"\C-xg": "get \M-?"
"\C-xt": "put \M-?"
"\M-.": yank-last-arg
$endif

8.4 可以绑定的Readline命令
本章介绍可以绑定键的 Readline 命令。
可以使用 bind -P 命令列出自己的键绑定;或者用 bind -p 更紧凑的列出,这样还适合放到 inputrc 文件中。
在下文中,标志点是指当前光标的位置,而记号是指用 set:mark 保存的光标位置。标志点和记号之间的文本叫做区域。
没有附带键序列的命令默认是没有绑定的。

8.4.1 Readline的移动命令
beginning-of-line ( C-a ) 移到到行的径头。
end-of-line ( C-e ) 移动到行的结尾。
forward-char ( C-f ) 向前移动一个字符。
backward-char ( C-b ) 向后移动一个字符。
forward-word ( M-f ) 向前移动到下一个单词的结尾。单词是由字母和数字构成的。
backward-word ( M-b ) 向后移动到前一个单词的开头。单词是由字母和数字构成的。
shell-forward-word 向前移动到下一个单词的结尾。单词是由未被引用的 shell 元字符分隔的。
shell-backward-word 向后移动到前一个单词的开头。单词是由未被引用的 shell 元字符分隔的。
clear-screen ( C-l ) 清屏并在屏幕顶端重新显示当前行,
redraw-current-line 刷新当前行。这个命令默认是没有绑定的

8.4.2 Readline的历史操作命令
accept-line ( Newline 或 Return ) 不管光标在哪都提交本行。如果本行不是空行,就按照HISTCONTROL和HISTIGNORE变量的设置把它加入到历史中。如果本行是修改历史行得到的,就恢复历史中原来的行。
previous-history ( C-p ) 在历史中向"后"移动得到上一个命令。
next-history ( C-n ) 在历史中向"前"移动得到下一个命令。
beginning-of-history ( 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-forward 在历史中当前行的开头和标志点之间向前搜索字符串。这是非增量搜索。这 个命令默认没有绑定。
history-search-backward 在历史中当前行的开头和标志点之间向后搜索字符串。这是非增量搜索。 这个命令默认没有绑定。
yank-nth-arg ( M-C-y ) 在标志点上插入前一个命令的第一个参数(通常是前一行的第二个单词)。
如果有参数 n,插入前一个命令的第 n 个单词(前一行的单词是从 0 开始数的)。
负的参数将插入从前一个命令的结尾弾始的第 n 个单词。
计算 n 的值以后,就会截取对应的参数,就好像指定了历史扩展"!n"一样。
yank-last-arg ( M-. 或 M- ) 插入前一个命令的最后一个参数(前一行的最后一个单词)。如果有参数,其行为就和 yank-nth-arg 完全一样。
连续调用 yank-last-arg 会在历史中向后移动,并依次插入每一行的最后一个参数。
最后一个参数是通过历史扩展机制取出来的,就好像指定了历史扩展"!$"一样。

8.4.3 Readline的文本修改命令
delete-char ( C-d ) 删除标志点处的字符。如果标志点在行的开头,行中没有字符,并且最后输入的字符没有绑定到 delete-char,则返回 EOF。
backward-delete-char ( Rubout ) 删除光标后面的字符。带有数值参数表示剪切这个字符,而不是删除。
forward-backward-delete-char 删除光标下面的字符;如果光标在行的结尾则删除光标后面的字符。这个命令默认没有绑定。
quoted-insert ( C-q 或 C-v ) 按字面意思插入后面输入的一个字符。例如,这样可以用来输入C-q 等键序列。
self-insert (a、b、A、1、!、...) 插入这些字符本身。
transpose-chars ( C-t ) 把光标前的字符向前拖动到光标下的字符上,同时把光标向前移动。如果插入点在行的结尾,则交换行中最后两个字符的位置。负的参数不起作用。
transpose-words ( M-t ) 把标志点前的单词拖过标志点后的单词,并把标志点移过这个单词。如果插入点在行的结尾,则交换行中最后两个单词的位置。
upcase-word ( M-u ) 把当前(或下一个)单词变为大写。如果有负的参数,则把前一个单词变为大写, 但不移动光标。
downcase-word ( M-l ) 把当前(或下一个)单词变为小写。如果有负的参数,则把前一个单词变为小写,但不移动光标。
capitalize-word ( M-c ) 把当前(或下一个)单词变为首字母大写。如果有负的参数,则把前一个单词首字母变为小写,但不移动光标。
overwrite-mode 切换覆盖模式。如果指定正数作为参数,则切换到覆盖模式;如果指定非正数参数,则切换到插入模式。
这个命令只影响 emacs 模式,而 vi 模式有不同的覆盖方法。每次启动 Readline时都进入插入模式。
在覆盖模式中,绑定到 self-insert 的字符会覆盖标志点后的字符,而不是把文本向右推动。
绑定到 backward-delete-char 的字符会把标志点前的字符用空格替换。这个命令默认没有绑定。

8.4.4 删除和复制
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 从标志点删除到当前单词的结尾;如果在单词之间,则删除到下一个单词的结尾。单词界限和 shell-forward-word 相同。
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 指定数字参数
digit-argument (M-0、M-1、... M-- ) 把这个数字加入到已收集数字的参数中,或者开始一个新的数字参数。 M-- 开始一个负的参数。
universal-argument 这是另外一种指定数字的方法。如果这个命令后面有一个或多个数字,数字前面可能还有负号,这些数字就是命令的参数。
如果这个命令后面是数字,则再次执行这个命令就会结束数字参数,否则就忽略这个命令。
特别的,如果紧接着这个命令后的字符既不是数字也不是负号,则后面的命令参数就扩大四倍。
参数初始值是一,所以第一次执行这个命令时参数就变成四,第二次就变成十六,以此类推。这个命令默认没有绑定。

8.4.6 补全命令
complete ( TAB ) 试图补全标志点前的文本。实际进行的补全是应用程序相关的。
补全时,Bash 依次把文本当作变量(如果以"$"开头)、或用户名(如果以"~"开头)、或主机名(如果以"@"开头)、或命令名(包括别名和函数)。
如果这些都不匹配,则试图进行文件名补全。
possible-completions ( M-? ) 列出能够补全标志点前的条目。
insert-completions ( M-* ) 把 possible-completions 命令能生成的所有文本条目插入到标志点前。
menu-complete 和 complete 类似,但是把要补全的文本替换成补全列表中的一个条目。
连续执行menu-complete 会在补全列表中依次前进,每次都插入当前条目。
前进到补全列表的结尾时就响铃(取决于 bell-style 的设置)并恢复原来的文本。
参数 n 表示在补全列表中向前移动 n 步;负参数表示向后移动。
这个命令本来是要绑定到 TAB 键,但默认没有绑定。
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 中使用。

8.4.7 键盘宏定义
start-kbd-macro ( C-x ( ) 开始把输入的字符保存在当前的键盘宏中。
end-kbd-macro ( C-x ) ) 结束把输入的字符保存在当前的键盘宏中,并保存键盘宏定义。
call-last-kbd-macro ( C-x e ) 重新执行刚刚定义的键盘宏,使得键盘宏的文本和用键盘输入的一样。

8.4.8 其它功能
re-read-init-file ( C-x C-r ) 读入 inputrc 文件的内容,并把其中任何绑定和变量赋值合并到当前会话中。
abort ( C-g ) 中止当前编辑的命令并响铃(取决于 bell-style 的配置)。
do-uppercase-version (M-a、M-b、M-x ...) 如果 Meta 化的字符是小写的,就运行对应大写字母绑定的命令。
prefix-meta ( ESC ) 把下一个字符 Meta 化。这是为没有 Meta 键的键盘准备的。键入 ESC f 就等价于输入 M-f 。
undo (C-或C-x C-u ) 增量撤销,可以分别对每行进行。
revert-line ( M-r ) 撤销对本行的所有修改。这就和多次执行 undo 命令以恢复到开始是一样的。
tilde-expand ( M-& ) 对当前的单词进行大括号扩展。
set:mark ( C-@ ) 在标志点设置记号。如果给定数值参数,则在指定位置设置记号。
exchange-point-and-mark ( C-x C-x ) 交换标志点的记号的位置。当前光标的位置变成已保存的位置;原来光标的位置设成记号。
character-search ( C-] ) 读取一个字符(作为参数)并把标志点移动到下一个同样的字符旁。负参数则向前移动。
character-search-backward ( M-C-] ) 读取一个字符(作为参数)并把标志点移动到上一个同样的字符旁。负参数则后前移动。
insert-comment ( M-# ) 如果没有数值参数,则把 comment-begin 变量的值插入到当前行的开始。
如果指定数值参数,这个数就作为开关:如果行开头的字符和 comment-begin 变量的值不一样就插入这个值,否则就把 comment-begin 变量里的字符从行的开头删除。
不管哪种情况,都提交本行,就好像输入了 Newline 一样。如果使用 comment-begin 的默认值,这个命令就会把当前行变成 shell 注释。
如果带有数值参数,就删除注释字符并把本行交给 shell 执行。
dump-functions 把所有函数和它们的键绑定打印到 Readline 的输出流中。
如果给定数值参数,就把输出格式化意以便于作为 inputrc 文件的一部分。这个命令默认没有绑定。
dump-variables 把所有可设置变量和它们的值打印到 Readline 的输出流中。
如果给定数值参数,就把输出格式化,以便于作为 inputrc 文件的一部分。这个命令默认没有绑定。
dump-macros 把 Readline 中所有绑定到宏的键序和它们绑定的字符串列打印出来。
如果给定数值参数,就把输出格式化,以便于作为 inputrc 文件的一部分。这个命令默认没有绑定。
glob-complete-word ( M-g ) 把标志点前的单词当成模式并隐式的在后面加上一个星号,然后进行文件名扩展。这个模式可以生成一系列匹配的文件名以用来补全。
glob-expand-word ( C-x * ) 把标志点前的单词当成模式并进行文件名扩展,把匹配的文件名列表插入进来并替换原来的单词。如果指定数值参数,就在文件名扩展之前先插入"*"。
glob-list-expansions ( C-x g ) 列出 glob-expand-word 可以生成的扩展并重新显示本行。如果指定数值参数,就在文件名扩展之前先插入"*"。
display-shell-version (C-x C-v) 显示当前 Bash 的版本信息。
shell-expand-line ( M-C-e ) 像 shell 一样扩展本行。它除了进行所有的 shell 扩展以外还要进行别名的历史扩展。
history-expand-line ( M-? ) 对当前行进行历史扩展。
magic-space 对当前行进行历史扩展并插入一个空格。
alias-expand-line 对当前行进行别名扩展。
history-and-alias-expand-line 对当前行进行历史和别名扩展。
insert-last-argument (M-.或M-) 和 yank-last-arg 是同义的。
operate-and-get-next ( C-o ) 提交并执行当前行,然后从历史中取出相对于当前行的下一行进行编辑。忽略任何参数。
edit-and-execute-command ( C-x C-e ) 启动一个编辑器来编辑当前行,并把结果当作 shell 命令来执行。Bash会试图依次启动 $VISUAL,$EDITOR 和 emacs 作为编辑器。

8.5 Readline的vi模式
尽管 Readline 库里面没有完整的 vi 编辑命令,却已经包含了足够的命令进行简单的行编辑。
Readline的 vi 模式在行为上遵循 POSIX 1003.2标准。可以使用 set -o emacs 和 set -o vi 命令在 emacs 和 vi 模式之间交互的切换。默认的是 emacs 模式。
在 vi 模式下输入文本行时已经进入了"插入"模式,就好像已经输入了 i 一样。
按下 ESC 会切换 到"命令"模式,这时可以用标准的 vi 移动键来编辑文本,用"k"移动到上一个历史行,用"j"移动到下一行,等等。

8.6 可编程的补全
如果已经使用内部命令 complete定义了补全的方法,则在对命令中的参数进行单词补全时,就会启用可编程的补全功能。
首先识别命令名。
如果已经为这个命令定义了 compspec 补全方法,就用 compspec 来生成一个可以补全当前单词的条目列表。
如果命令词是一个完整路径,则首先用 compspec 生成一个完整路径的补全列表;
如果没有指定生成完整路径的 compspec,就会试图找到一个能生成路径中最后一个斜杠后面的部分路径的补全列表。
找到 compspec 以后,就用它来生成和当前单词匹配的条目列表。
如果没有找到,Bash 就生成默认的补全列表。
首先,执行 compspec 指定的动作。这时只返回以待补全单词作为前缀的条目。如果在补全文件或目录名时指定了"-f"或"-d"选项,就会使用 shell 变量 FIGNORE来过滤匹配的条目。
其次,扩展"-G"选项的文件名模式并生成补全列表。根据模式生成的单词不一定要和待补全的单词匹配。这时不会使用 shell 变量 GLOBIGNORE 来过滤匹配的条目,而使用 FIGNORE 过滤。
然后,处理"-W"选项指定的字符串参数。
首先用特殊变量 IFS 中的字符作为分隔符把这个字符串分开。 这时会使用 shell 的引用机制。
然后对每个单词进行在括号扩展、波浪号扩展、参数和变量扩展、命令替换、 以及算术扩展,并对扩展结果进行单词拆分。
扩展的结果加上待补全的单词作为前缀;这样匹配的单词就成为可以补全的条目。
生成匹配的条目以后,就执行"-F"和"-C"选项指定的任何 shell 函数和命令。执行这些函数或命令时,会对COMP LINE、COMP POINT、COMP KEY、和 COMP TYPE 变量进行赋值。
如果执行的是 shell 函数,则还会设置COMP WORDS和COMP CWORD变量。
执行函数或命令时,第一个参数是等待补全其参数的命令的名称,第二个参数是要补全的单词,第三个参数是在当前命令中待补全单词的前一个单词。
这时不会按照待补全的单词对生成的补全条目进行过滤;而所执行的函数或命令可以完全自由的控制生成的条目。
"-F"指定的函数将被执行。这个函数可以使用任何 shell 功能来生成匹配条目,包括下面的内部命令 compgen 和 compopt,但是它必须把补全条目放在数组变 COMPREPLY中。
接下来,在类似于命令替换的环境中执行"-C"选项指定的命令。这个命令应该在标准输出中打印出匹配条目,每个一行。如有必要,可以使用反斜杠来转义换行符。
当所有补全条目都生成好以后,"-X"选项指定的过滤器过滤条目列表。这个过滤器是一个模式,就和文件名扩展的模式一样。
模式中的"&"将替换成待补全的文本;而"&"本身可以用反斜杠转义,在匹配之前反斜杠会被去除。与这个模式匹配的条目将从列表中删除。
模式中前导的"!"表示否定,这种情况下会删除所有与模式不匹配的条目。
最后,对补全列表的每个条目加上"-P"和"-S"选项指定的前缀和后缀,并把结果作为最终补全列表返回给 Readline 的补全代码。
如果上一次执行的动作没有生成任何条目,并且在定义 compspec 时指定了"-o dirnames",则将试图进行目录名称补全。
如果定义 compspec 时指定了"-o plusdirs"选项,则会试图进行目录名称补全,并加上其它动作生成的任何补全条目。
默认情况下,如果找到一个 compspec,则不管它生成什么,都将完整的返回给补全代码;这时不会进行 Bash 默认的补全,也不会进行 Readline 默认的文件名补全。
在定义 compspec 时,可以使用"-o bashdefault"选项,这样如果 compspec 没有生成任何条目就会试图进行 Bash 默认的补全。
在定义compspec 时,可以使用"-o default"选项,这样如果 compspec 没有生成任何条目(并且如果试图进行Bash 默认的补全也没有生成任何条目)就会试图进行 Readline 默认的补全。
如果 compspec 指示进行目录名称补全,则可编程的补全功能会强制 Readline 在每个指向目录的符号链接后面加上斜杠(取决于 Readline 的 mark-directories 变量),而不管 Readline 的 mark-symlinked-directories变量如何设置。

8.7 可编程补全的内部命令
可编程补全的功能是由两个命令实现的。此外,还可以特殊的设置补全的选项。
8.7.1 compgen
语法:compgen [选项] [单词]
根据选项生成与单词相匹配的补全,并写到标准输出中;
这些选项可以是内部命令 complete 所能接受的任何选项,但不能是"-p"和"-r"。
如果使用了"-F"或"-C"选项,则由可编程补全功能设置的各个 shell 变量虽然仍可以使用,它们的值却没有什么作用。
生成的补全条目就好像可编程补全的代码用相同的选项按照补全方法直接生成的一样。
如果指定了单词,则只显示匹配该单词的条目。返回状态是真,除非指定了无效的选 项,或没有生成任何匹配条目。

8.7.2 complete
语法:complete [-abcdefgjksuv] [-o 补全选项] [-E] [-A 动作] [-G 模式] [-W 单词列表] [-F 函数] [-C 命令] [-X 过滤模式] [-P 前缀] [-S 后缀] 名称 [名称 ...]
complete -pr [-E] [名称...]
指定如何对每个名称进行补全。
如果指定了"-p"选项,或者没有指定任何选项,则把已有的补全方法用一种便于重新作为输入的格式打印出来。"-r"选项会把每个名称的补全方法删除。

对单词进行补全时处理补全方法的过程已经在上文中介绍 。
如果指定了其它选项,则会有如下的含义。
"-G"、"-W"、和"-X"选项(如有必要,还有"-P"和"-S"选项)的参数需要引用,以防止它们在补全开始前被扩展。
-o 补全选项 除了简单的生成补全条目以外,补全选项还控制着 compspec 的多方面行为。
补全选项可以是:
bashdefault 如果 compspec 没有生成任何条目就进行 Bash 默认的其它补全。
default 如果 compspec 没有生成任何条目就使用 Readline 默认的文件名补全。
dirnames 如果 compspec 没有生成任何条目就进行目录名称补全。
filenames 告诉 Readline 由 compspec 生成文件名,以便进行与文件名相关的处理 。这个选项是为和"-F"选项所指定的函数一起使用而设计的。
nospace 告诉 Readline 不要在结尾补全的单词后添加空格。
plusdirs 生成 compspec 定义的所有匹配条目后,还试图进行目录名补全,并把生成的条目加入到其它动作得到的结果中。
"-E"选项告诉后续选项和动作要补全"空"命令,即补全空白行
-A 动作 动作可以是下列之一;它用来生成补全条目。
alias 所有别名。还可以指定为"-a"选项。
arrayvar 所有数组变量名。
binding Readline 的所有键绑定名。
builtin 所有的 shell 内部命令名。还可以指定为"-b"选项。
command 所有的命令名。还可以指定为"-c"选项。
directory 所有的目录名。还可以指定为"-d"选项。
disabled 所有已经禁用的 shell 内部命令。
enabled 所有已经启用的 shell 内部命令。
export shell导出的所有变量名。还可以指定为"-e"选项。
file 所有的文件名。还可以指定为"-f"选项。
function 所有的 shell 函数名。
group 所有的用户组名。还可以指定为"-g"选项。
helptopic 内部命令 help所接受的所有帮助主题。
hostname shell变量 HOSTFILE指定文件中的所有主机名。
job 如果使用了作业控制,则是所有作业的名称。还可以指定为"-j"选项。
keyword shell 中的所有保留字。还可以指定为"-k"选项。
running 如果使用了作业控制,则是所有正在运行的作业。
service 所有的服务名称。还可以指定为"-s"选项。
setopt 内部命令 set 的"-o"选项所接受的所有有效参数。
shopt 内部命令 shopt 所接受的所有 shell 选项名称。
signal 所有信号名称。
stopped 如果使用了作业控制,则是所有已停止的作业名称。
user 所有用户名。还可以指定为"-u"选项。
variable 所有 shell 变量的名称。还可以指定为"-v"选项。
-G 模式 对模式进行文件名扩展来生成补全条目。
-W 单词列表 使用特殊变量 IFS 中的字符拆分单词列表并扩展拆分后的每个单词。结果中与待补全单词匹配的条目就是补全条目。
-C 命令 在子 shell 中执行命令,并把其结果作为补全条目。
-F 函数 在当前的 shell 环境中执行 shell 函数。结束执行时,从数组变量 COMPREPLY 中获取补全条目。
-X 过滤模式 它是进行文件名扩展时使用的模式。它作用于通过前面的选项和参数生成的补全列表,并把每个与过滤模式匹配的条目删除。
模式中前导的"!"表示否定;这时会删除与过滤模式不匹配的条目。
-P 前缀 在处理完所有其它的选项后,给每个补全的条目加上前缀。
-S 后缀 在处理完所有其它的选项后,给每个补全的条目加上后缀。
返回状态是真,除非指定了无效的选项、或者指定了"-p"或"-r"之外的选项却没有指定名称参数、或者修改了名称中没有任何补全方法定义过的一个选项、或者输出时发生错误。

8.7.3 compopt
语法:compopt [-o 选项] [+o 选项] [名称]
修改每个名称指定的补全选项;如果没有指定名称则修改当前执行的补全的选项。
如果也没有指定选项,则显示每个名称或当前补全所用的选项。
选项可能的取值就是上面的内部命令 complete 的有效选项。
返回状态是真,除非指定了无效的选项、或者修改了名称中没有任何补全方法定义过的一个选项、或者输出时发生 错误。

猜你喜欢

转载自www.cnblogs.com/BradMiller/p/11858334.html