8.5.3 Readline库
Bourne Again Shell的命令行编辑功能通过Readline库实现,任何用C语言编写的应用程序都可以使用这个库。任何使用Readline库的应用程序都可以支持bash提供的行编辑功能。使用Readline库的应用程序(包括bash)通过读取文件~/.inputrc获取键绑定信息和配置设置。命令行选项--noediting可将bash的命令行编辑功能关闭。
vi模式 在bash中使用Readline库的时候,用户可以选择两种编辑模式,即emacs模式和vi模式。两种模式均提供了很多独立版本vi或者emacs中具备的命令。还可以使用方向键来回移动。向上移动和向下移动可以在历史列表中前后滚动。另外,Readline还提供了几种类型的交互式字自动补全功能。默认模式是emacs模式,使用下面的命令可以切换到vi模式:
$ set –o vi |
emacs模式 下面的命令可重新切换回emacs模式:
$ set –o emacs |
1. vi编辑模式
在开始下面的内容之前,检查一下是否已处于vi模式。
在vi模式下,当输入bash命令时,用户处于输入模式。当用户输入一条命令,如果在按下RETURN键之前发现了一个错误,可以输入换码符(ESC)以切换到vi命令模式。这种设置与独立版的vi编辑器的初始模式不同。当处于命令模式时,用户可以使用vi命令来编辑命令行。这种情形类似于在vi中,用一个只有一行命令空间的屏幕编辑历史文件的副本。当使用k命令或者向上键向上移动一行时,可以访问前一条命令。而使用j命令或者向下键向下移动一行时,则可以返回到起初的那条命令。必须在命令模式下,才可以使用k和j键在命令之间移动。在命令模式和输入模式下均可以使用上下键。
在命令模式下启动独立版的编辑器
提示 独立版vi编辑器启动时处于命令模式,而命令行vi编辑器启动时处于输入模式。如果命令显示字符但是不能正常工作,那么用户处于输入模式;按下ESC键,就会再次进入命令模式。
除光标定位命令之外,还可以使用后面跟着一个搜索串的向后搜索命令(?),它在命令历史列表中搜索,以查找包含该字符串的最近的命令。如果已经在历史列表中向后移动了,使用正斜杠(/)向前搜索最近的命令。与独立版的vi编辑器中的搜索串不同,这些搜索串不能包含正则表达式。但是,用户可在搜索串的开始处加上脱字符(^),强迫shell找到以该搜索串开头的命令。与在vi中一样,在一次成功搜索之后输入n,将查找相同串的下一次出现位置。
还可以使用事件编号来访问历史列表中的事件。当处于命令模式(按下ESC键)时,输入事件编号,后面跟着G,将跳转到该事件编号表示的那条命令。
如果使用/、?或者G移动到某个命令行,那么此时用户处于命令模式,而不是输入模式。此时,如果需要,用户可以编辑该命令,或者按下RETURN键执行该命令。
一旦想要编辑的那条命令显示出来,就可以使用vi命令模式编辑命令如x(删除字符)、r(替换字符)、~(改变大小写)和.(重复上次修改)来修改该命令行。使用插入(i或者I)、追加(a或者A)、替换(R)或者修改(c或者C)命令可以进入输入模式。要想运行命令,不必回到命令模式,简单地按下RETURN键即可,即使光标正处于该命令行的中间某个位置也能执行命令。
参考第6.15节的vim命令小结。
2. emacs编辑模式
与vi编辑器不同,emacs没有模式。用户不必在命令模式和输入模式之间切换,因为大多数emacs命令是些控制字符,这样emacs就可以区分输入和命令。与vi类似,emacs命令行编辑器也提供了命令,用于在命令行上移动光标、在历史列表中滚动,以及修改某条命令的部分或者全部内容。emacs命令行编辑器的命令与独立版emacs编辑器的命令有些不同。
在emacs中,可以同时使用CONTROL和ESCAPE命令移动光标。按下CONTROL+B组合键可将光标在命令行上向后移动一个字符。按下CONTROL+F组合键可以在命令行上向前移动一个字符。与在vi中一样,可在这些移动前面加上数字。要想使用数字,必须首先按下ESCAPE键,否则用户输入的数字将出现在命令行上。
与vi类似,emacs提供了字移动命令和行移动命令。按下ESCb或者ESCf,可以在命令行上向后或者向前移动一个字。要想使用数字以移动多个字,可以按下ESC键,后面跟着数字,然后再输入相应的转义字符序列。按下CONTROL+A组合键,可以跳到命令行的行首;而按下CONTROL+E组合键,则可以跳到行末。按下CONTROL+X CONTROL+F然后跟着c,就可以跳到字符c的下一次出现的地方。
将光标移动到适当的位置并输入想要的文本,这样就可以将文本添加到命令中。而要想删除文本,首先将光标移动到想要删除的字符的右侧,然后依次按下删除键,删掉那些想删除的字符。
CONTROL+D可能会终止屏幕会话
提示 如果想直接删除光标前的字符,那么按下CONTROL+D组合键即可。而如果在文件开头处按下CONTROL+D组合键,那么用户的shell会话将会终止。
如果想删除整行命令,那么可以输入行删除字符。当光标处于命令行中的任何位置时,用户都可以输入这个字符。用CONTROL+K可以删除光标到行末的所有字符。
参见第7.9节中的emacs命令小结。
3. Readline命令补全
当用户在命令行中输入命令时,可以使用制表符键(TAB)来补全字。这项功能称为补全,在vi和emacs编辑模式下均可用,类似于tcsh中的补全功能。可能会有多种类型的补全,使用哪种类型取决于用户在按下TAB键时,用户正在输入命令行的哪部分。
(1) 命令补全
如果用户正在输入一个命令的名字(命令行的第1个字),这时按下TAB,将执行命令补全。也就是说,bash查找名字以用户刚刚输入的字开头的命令。如果没有以用户已输入的字开头的命令,shell将发出蜂鸣声。如果仅存在一条这样的命令,bash将自动为用户补全命令名。如果有多个选择,那么若在vi模式下,则bash会发出蜂鸣声,而若在emacs模式下,bash则不采取任何行动。再次按下TAB键,bash将显示以用户输入的字为前缀的命令列表,并允许用户来完成命令名的输入。
在下面的示例中,用户输入bz并按下了TAB键。shell发出蜂鸣声(用户处于emacs模式),以提示有多个以字母bz开头的命令。该用户再次按下TAB键,shell将显示一个以bz开头的命令列表,后面跟着该用户目前已经输入的命令行:
$ bz —> TAB (beep) —> TAB |
然后,用户输入c并按TAB键两次。shell显示两个以bzc开头的命令。用户输入a,后面跟着TAB,shell补全这条命令,因为此时只有一个命令以bzca开头。
$ bzc —> TAB (beep) —> TAB |
(2) 路径名补全
路径名补全也使用TAB键,用户可以只输入一部分路径名而由bash提供剩余部分。如果用户输入的部分路径名已经足以确定一个唯一的路径名,那么bash将显示该路径名。如果有多个路径名匹配,那么bash将补充路径名直到那个有多个可选的点为止,等待用户进一步输入。
当用户输入一个路径名,包括一个简单的文件名,然而按TAB键,shell将发出蜂鸣声(如果shell为emacs模式;而若处于vi模式则没有蜂鸣声)。然后shell将尽可能地扩充该命令行。
cat films/dar —> TAB (beep) cat fi1ms/dark_■ |
在films目录下面,每个以dar开头的文件的下几个字符都是k_,因此在这些文件中做出选择之前,bash不能进一步扩充命令行。此时光标仅仅在字符_之后。在这个点上,可以继续输入路径名或者再次按下TAB键。如果再次按下TAB键,bash将发出蜂鸣声,显示可供选择的项,再次显示命令行,然后再次将光标放到字符_之后。
$ cat films/dark_ —> TAB (beep) —> TAB |
当用户输入足够的信息可区分两个可能的文件并按下TAB键时,bash显示这个唯一的路径名。如果在字符_之后输入p,后面跟着TAB键,那么shell将完成命令行:
$ cat fi1ms/dark_p —> TAB —> assage |
因为没有更多的模糊名字,shell附加了一个空格符,这样用户就可以完成命令行,或者按下RETURN键执行该命令。如果完整的路径名是一个目录,bash将在空格符的地方附加一个斜杠符(/)。
(3) 变量补全
当输入变量名时,按下TAB键将会进行变量补全操作,即bash将试图完成该变量的名称。当遇到歧义时,按下TAB键两次将显示可选项的列表:
$ echo $HO —> TAB —> TAB |
按下RETURN键将执行命令
警告 无论光标处于命令行中的什么位置,按下RETURN键都将让shell执行该命令。
4. .inputrc:配置Readline
使用Readline库的Bourne Again Shell和其他程序都会读取由INPUTRC环境变量指定的文件,以获取初始化信息。如果没有设置INPUTRC,这些程序将从文件~/.inputrc中读取。这些程序忽略文件.inputrc中的空白行或者以#号(#)开头的行。
(1) 变量
可以在.inputrc文件中设置变量以控制Readline库的行为。其语法如下:
set veriable value |
表8-11列出了一些变量以及可以使用的值。查阅bash的man页或者info页中的“Readline变量”部分,以获得完整的列表。
表8-11 readline库
|
变 量 |
作 用 |
|
editing-mode |
设置为vi以使Readline在vi模式下启动;设置为emacs以使Readline在emacs模式下启动(默认);类似于shell命令set -o vi和set -o emacs |
|
horizontal-scroll-mode |
设置为on将使较长的行扩展到显示区域的右侧边界;当光标在显示区域的右侧边界时,向右移动光标将把该行左移,这样用户就可以看到本行的更多内容;向左移动光标跨过左侧边界就可以将该行移动回去;默认值为off,这将使得较长的行在显示区域被自动换行成多行显示 |
(续表)
|
变 量 |
作 用 |
|
mark-directories |
设置为off将使Readline在完成补全时,不用在目录名的末尾处放置斜杠符(/);一般设置为on |
|
mark-modified-lines |
设置为on将使Readline在被修改的历史行前面加上星号;默认值为off |
(2) 键绑定
用户可以指定按键序列到Readline命令的映射绑定,如此可修改或者扩充默认的绑定。与在emacs中一样,Readline库包含了很多没有绑定到按键序列的命令。要想使用某个未绑定的命令,用户必须使用下面几种方式之一将其映射:
keyname: command_name |
在第1种形式中,用户可以为每个单独的键拼出名字。比如,CONTROL+U被写作control-u。在为单个键进行命令绑定时这种形式很有用。
在第2种形式中,用户指定了一个描述绑定到命令上的按键序列的字符串。可以使用emacs风格的反斜杠转义序列来描述特殊的键如CONTROL(\C)、META(\M)和ESCAPE(\e)。而通过另一个反斜杠可将反斜杠转义:\\。类似地,双引号或者单个引号也可用反斜杠转义:\”或者\’。
kill-whole-line命令只在emacs模式下才有,该命令用于删除当前行。将下面的命令放入到文件.inputrc中,就可以将kill-whole-line命令绑定到按键序列CONTROL+R上。
control-r: kill-whole-line |
bind 命令bind -P显示所有Readline命令列表。如果某个命令绑定到按键序列上,该按键序列就会显示出来。可以在vi模式下使用的命令均以vi开头。比如,vi-next-word和vi-prev-word命令将光标相应地移动到下一行或者前一行的开始处。那些不以vi开头的命令在emacs模式下可用。
使用bind -q可判断某条命令绑定到哪个按键序列:
$ bind -q kin-whole-line |
可以用双引号将文本括起来(只在emacs模式下可用),以绑定该文本:
"QQ": "The Linux Operating System" |
使用该命令后,当用户输入QQ时,bash就会插入字符串The Linux Operating System。
(3) 条件结构
使用$if指令可以根据条件选择.inputrc文件的一部分。条件结构的语法如下:
$if [test[=value]] commands |
其中,test为mode、term或者bash。如果test等于value或者test为true,那么这个结构就执行第1组命令。如果test不等于value或者test为false,并且第2组命令不为空,则执行这组命令,否则退出该结构。
$if指令的作用在于它可以执行3种类型的测试。
① 可以测试当前设置的模式。
$if mode=vi |
如果当前的Readline模式为vi,前面的测试就为true,否则为false。可用来测试vi或者emacs。
② 可以测试终端类型。
$if term=xterm |
如果TERM变量设置为xterm,前面的测试就为true。可用来测试TERM的任何值。
③ 可以测试应用程序名称。
$if bash |
如果正在运行bash并且没有其他程序使用Readline库,那么前面的测试就为true。可以测试任意应用程序名称。
基于当前模式、终端类型和正在使用的应用程序,用户可用这些测试定制Readline库。当与bash和其他程序一起使用Readline库的时候,这些测试可以提供很强的功能和很大的灵活性。
下面的命令位于.inputrc文件中,按下CONTROL+Y组合键可移动光标到下一个字的起始处,不论bash处于vi模式还是emacs模式:
$ cat ~/. inputrc |
因为bash启动的时候读取这个条件结构,所以在.inputrc文件中设置编辑模式。使用set命令交互式地改变模式并不能改变CONTROL+Y的绑定。
要获得更多关于Readline库的信息,请打开bash的man手册页,并输入命令/^READLINE,该命令将在每行起始处搜索字READLINE。
如果Readline命令不能运行,请注销并再次登录
提示 当用户登录的时候,Bourne Again Shell读取~/.inputrc文件。当改变该文件之后,要想测试这些修改,应该首先注销然后再次登录。
| 回书目 上一节 下一节 |