首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 开源 FAQ 第二书店 博文视点 程序员
频道: 研发 数据库 中间件 信息化 视频 .NET Java 游戏 移动 服务: 人才 外包 培训
    图书品种:235680
       
热门搜索: ASP.NET Ajax Spring Hibernate Java

8.5  命令历史机制

历史机制是一项对C shell的改造功能,它维护了用户最近发出的命令行(也称为事件)的列表,这就为重新执行列表中任何事件提供了一个便捷的方式。用户还可以使用这套机制来执行前面命令的变种,并重用它们的参数。用户可以复制前面在本次登录会话中使用的或者前一次会话中使用的复杂命令和参数,并输入那些只是有细微差别的一系列命令。历史列表还记录用户使用过程。当发生错误但是又不确定何处出错或者希望记录一系列命令的过程的时候,这套机制非常有用。

内置命令history(在bash和tcsh中均可用)显示了历史列表的内容。如果该命令不能显示,通过后续阅读,用户会发现还需要设置一些变量。

 

命令历史有助于跟踪错误 

提示

当发生了一个命令行错误(不是在脚本或者程序中),但又不确定到底是哪个地方出错,此时可以查看历史列表,浏览最近输入的命令。有些时候,这个列表将有助于用户搞清楚到底什么地方出错以及如何修改错误。

8.5.1  控制历史机制的变量

TC Shell的历史机制与bash相似,但是使用了不同的变量,并且还有其他差异。参见第9.3节以获取更多信息。

HISTSIZE变量的值决定了在某次会话期间历史列表中保存的事件数目。该值的范围正常情况下是100~1000。

当从shell中退出时,最近执行的命令将保存在HISTFILE变量执行的文件中(默认是~/.bash_history)。下一次启动shell时,将使用这个文件来初始化历史列表。变量HISTFILESIZE的值决定了保存在HISTFILE中的历史行数(不一定与HISTSIZE相同)。HISTSIZE保存了会话期间记忆的事件数目,HISTFILESIZE则保存了会话之间记忆的数目,LISTFILE指定了保存历史列表的文件,如表8-7所表示。

表8-7  历史变量

变    量

默  认  值

功    能

HISTSIZE

500个事件

在一次会话期间保存的最大事件数目

HISTFILE

~/.bash_history

历史文件的位置

HISTFILESIZE

500个事件

会话之间保存的事件最大数目

事件编号  Bourne Again shell连续地为每行命令指派了一个事件编号。如果在PS1中包含“\!”,则可以将事件编号作为bash提示符的一部分显示出来。本节的示例中,如果有助于为了演示命令的行为,就给出了事件编号提示符。

手动输入下列命令或者将其放置在文件~/.bash_profile中(可以影响到后面的会话),就可以建立一个能够容纳100条最近事件的历史列表:

$ HISTSIZE=100

下面的命令可使bash在两次登录会话之间保存100条最近的事件:

$ HISTFILESIZE=100

在用户设置了HISTFILESIZE之后,如果用户注销之后再次登录,那么前一次登录会话中的100条最近事件都将出现在历史列表中。

输入history命令可以显示历史列表中的事件。事件列表按照最早的事件排在列表顶部的顺序排列。tcsh历史列表还包含了命令开始执行的时间。下面的历史列表中包含了一条修改bash提示符的命令,因此显示了历史事件编号。历史列表中的最后一个事件是用来显示这个列表的history命令。

32 $ history | tail

23 PS1="\! bash$ "

24 ls -1

25 cat temp

26 rm temp

27 vim memo

28 lpr memo

29 vim memo

30 lpr memo

31 rm memo

32 history | tail

在运行命令时,历史列表将变得越来越长,这样当使用内置命令history的时候,显示内容可能超出屏幕顶部。这时可将history的输出通过管道发送给less,以浏览历史列表。还可以使用命令history 10来显示最近的命令。

8.5.2  重新执行和编辑命令

可以重新执行历史列表中的任何事件。这项功能可以省时、省力和省心。不需要重新输入长长的命令行可使用户更加容易、更加快速和精确地重新执行事件,这样做的效率要比重新输入完整的命令行高得多。可以采用3种方式来浏览、修改和重新执行前面已执行的命令,即使用内置命令fc(下面将讲到)、使用感叹号命令以及Readline库,该库使用单行类vi编辑器和类emacs编辑器来编辑和执行事件。

 

使用哪种方法? 

提示

如果比较熟悉vi或者emacs和less而不熟悉C Shell或者TC Shell,那么可以使用fc或者Readline库。如果比较熟悉C Shell或者TC Shell而不熟悉vi和emacs,那么可以使用感叹号命令。如果没有办法做出判断,可以尝试Readline库,它可以使用户在Linux的其他领域获益,而不仅仅是学习感叹号命令。

1. fc:显示、编辑和重新执行命令

内置命令(tcsh中没有)fc(fix command,修改命令)可用来显示历史列表内容,并可以编辑和重新执行前面的命令。它提供了命令行编辑器很多相同的功能。

(1) 查看历史列表

带上-l选项调用fc时,fc显示历史列表中的命令。如果不带任何参数,那么fc -l将在编号列表中显示最近的16个命令,最早的命令出现在列表首位:

$ fc -1

1024     cd

1025     view calendar

1026     vim letter.adams01

1027     aspell -c letter.adams01

1028     vim letter.adams01

1029     lpr letter.adams01

1030     cd ../memos

1031     ls

1032     rm *0405

1033     fc -1

1034     cd

1035     whereis aspell

1036     man aspell

1037     cd /usr/share/doc/*aspele*

1038     pwd

1039    ls

1040    ls man-html

内置命令fc的-l选项可以带有零个、一个或者两个参数。这些参数指定了历史列表中将要显示的部分:

fc -l [first [last]]

内置命令fc列出了以匹配first参数的最近事件为开头的命令。这个参数可以是一个事件编号,或者是命令行开头的几个字符,还可以是一个负数,它表示当前fc命令之前的第n条命令。如果给出last参数,fc命令将显示从匹配first的最近事件到匹配last的最近事件的命令。下面一条命令显示了从事件1030~事件1035之间的历史列表:

$ fc -1   1030 1035

1030       cd ../memos

1031        is

1032        rm *0405

1033        fc -1

1034        cd

1035        whereis aspell

下面的命令列出了以view开头到以whereas开头的所有最近事件:

$ fc -1 view whereis

1025     view calendar

1026     vim letter.adams01

1027     aspell -c letter.adams01

1028     vim letter.adams01

1029     lpr letter.adams01

1030     cd ../memos

1031     ls

1032     rm *0405

1033     fc -1

1034     cd

1035     whereis aspell

为了列出历史列表中的单个命令,可以使用同一个标识符作为第1个参数和第2个参数。下面的命令列出了事件1027:

$ fc -1 1027 1027

1027      aspell -c letter.adams01

(2) 编辑和重新执行前面的命令

可用fc编辑和重新执行前面的命令。

fc [-e editor] [first [last]]

当带有-e选项调用fc时,如果后面还带有某个编辑器的名字,那么fc将调用该编辑器,并将事件放在工作缓冲区中。如果不带firstlast参数,fc默认为最近命令。下面的示例调用vi(vim)编辑器来标记最近使用命令:

$ fc –e vi

内置命令fc使用独立的vi(vim)编辑器。如果设置了FCEDIT变量,那么就没有必要在命令行中再使用-e选项指定编辑器。在下面的命令中,因为已经将FCEDIT的值改为/usr/bin/emacs,并且fc没有带参数,所以该命令将使用emacs编辑器编辑最近的那条命令:

$ export FCEDIT=/usr/bin/emacs

$ fc

如果只带一个参数调用fc,那么fc将调用编辑器编辑指定命令。下面的示例开启编辑器,并将事件21放在工作缓冲区中。当退出编辑器的时候,shell将执行该命令:

$ fc 21

用户还可以用编号或者通过指定命令名开头几个字符的方式来标识命令。下面的示例调用编辑器编辑从以字母vim开头的最近事件到事件206之间的事件:

$ fc vim 206

 

清除fc缓冲区 

提示

当执行fc命令时,shell将执行存放在编辑器缓冲区中的任何内容,这很可能导致未预期的结果。如果用户决定不执行命令,那么请在退出之前删除缓冲区中的所有内容。

(3) 不调用编辑器而重新执行命令

可以不进入编辑器的情况下重新执行前面的命令。如果调用fc时,带上-s选项,那么它将跳过编辑阶段,并重新执行该命令。下面的示例将重新执行事件1029:

$ fc -s 1029

lpr 1etter.adams01

下一个示例重新执行前一条命令:

$ fc -s

当重新执行某条命令时,可以让fc用一个字符串代替另一个字符串。下一个示例用字符串john替换了事件1029中的字符串adams,并执行修改后的事件:

$ fc -s adams=john 1029

lpr letter.john01

2. 使用感叹号(!)引用事件

C Shell的历史机制使用感叹号来引用事件,这在bash和tcsh中同样有效。尽管使用感叹号比fc更繁琐,但是它具有很多有用的特性。比如!!命令重新执行前一个事件,!$符号表示前一个命令行中的最后一个字。

可以使用事件的绝对编号、相对编号或者事件中包含的文本来引用该事件。所有的事件引用(称为事件标志符)均以感叹号!开头。感叹号后面的一个或者多个字符指定某个事件。

可以在命令行中的任何地方放置历史事件。在感叹号前面加上反斜杠(\),或者用单引号将其括起来,就可以将感叹号转义,从而将其作为一个普通字符对待,而不是作为某个历史事件的开头。

事件标志符

事件标志符指定了命令历史中的某条命令。表8-8给出了事件标志符列表。

表8-8  事件标志符

标  志  符

含    义

!

除非后面紧接着空格符、换行符、=或者(,否则立即开始某个历史事件

!!

前一个命令

!n

历史列表中编号为n的命令

!-n

往前第n条命令

!string

最近以string开头的命令行

!?string[?]

包含string的最近命令行;最后的?是可选的

!#

当前命令(目前输入的部分)

!{event}

event为一个事件标志符;花括号将event与左右的文本隔开;比如,!{-3}3表示后面跟着3的第3个最近执行的命令

用!!命令重新执行前一个事件  总是可以使用!!命令重新执行前一个事件。下面的示例中,事件45重新执行了事件44:

44 $ ls -1 text

-rw-rw-r--   1 alex group 45 Apr 30 14:53 text

45 $ !!

ls -1 text

-rw-rw-r--   1 alex group 45 Apr 30 14:53 text

无论提示符是否显示事件编号,!!命令都可以正常工作。正如这个示例,当使用历史机制重新执行某个事件时,shell显示它正在重新执行的命令。

!n事件编号  感叹号后面跟着一个数字表示对某个事件的引用。如果该事件在历史列表中,shell将执行它。否则,shell显示一条错误消息。感叹号后面跟着一个负数表示相对于当前事件的事件的引用。比如,命令!-3将执行从当前命令往前数第3个事件。在用户输入一条命令之后,给定事件的相对事件编号发生改变(事件-3变成了事件-4)。下面的两条命令均重新执行事件44:

51 $ !44

ls -1 text

-rw-rw-r--   1 alex group 45 Nov 30 14:53 text

52 $ !-8

ls -1 text

-rw-rw-r--   1 alex group 45 Nov 30 14:53 text

!string事件文本  当在感叹号后面跟着一个文本串时,shell搜索并执行最近的以该文本串开头的事件。如果将该文本串用问号封起来,那么,shell将执行最近的包含该文本串的事件。如果命令立即以RETURN符结尾,那么最后的问号就是可选的。

68 $ history 10

59 ls -l text*

60 tail text5

61 cat textl text5 > letter

62 vim letter

63 cat letter

64 cat memo

65 ipr memo

66 pine jenny

67 ls -1

68 history

69 $ !1

ls -1

...

70 $ !1pr

lpr memo

71 $ !?1etter?

cat letter

...

选读

3. 字标志符

字标志符指定了事件中的某个字或者一组字。表8-9列出了字标志符。

表8-9  字标志符

标  志  符

含    义

n

n个字;一般情况下,字0就是命令名

^

第1个字(紧随命令名)

$

最后那个字

m-n

从编号mn的所有字,如果忽略m,那么m默认为0(0-n)

n*

从第n个到最后那个之间的所有字

*

除命令名之外的所有字;与1*相同

%

最近的匹配?string?搜索的那个字

这些字的编号从0开始(命令行上的第1个字,通常就是命令名称),接着是1(紧接命令名的第1个字),直到n(命令行上的最后一个字)。

为了指定前一个事件中的某个特定的字,在事件标志符(如!14)后面跟着一个冒号和一个表示该字在这个命令中的标号。比如,!14:3指定了事件14中命令名后第3个字。可以使用脱字符(^)指定命令名后第1个字(字编号为1),最后一个字则可用美元符号($)表示。使用一个用连字符隔开的两个字标志符,可以指定字范围。

72 $ echo apple grape orange pear

apple grape orange pear

73 $ echo !72:2

echo grape

grape                    

74 $ echo !72:^

echo apple

apple

75 $ !72:0 !72:$

echo pear

pear

76 $ echo !72:2-4

echo grape orange pear

grape orange pear

77 $ !72:0-$

echo apple grape orange pear

apple grape orange pear

如下一个示例所示,!$表示前一个事件的最后一个字。举例来说,可以使用这个速记符号编辑cat刚刚显示的那个文件:

$ cat report.718

...

$ vim !$

vim report.718

...

如果一个事件只包含了单个命令,那么字编号就与参数编号相对应。如果事件包含了多条命令,那个对于第1条之后的命令来说,这种对应关系将不再成立。在下面的示例中,事件78包含了用分号隔开的两条命令,这样shell将同时执行这两条命令,这个分号的字编号是5。

78 $ !72 ; echo helen jenny barbara

echo apple grape orange pear ; echo helen jenny barbara

apple grape orange pear

helen jenny barbara

79 $ echo !78:7

echo helen

helen

80 $ echo !78:4-7

echo pear ; echo helen

pear

helen

4. 修饰符

有时候需要改变正要重新执行的命令的某些地方。可能在输入某个复杂命令行出现错误,或者有一个不正确的路径名,又或者想指定某个不同的参数。通过在字标志符后面或者事件标志符后面(如果没有字标志符)放置一个或者多个修饰符,就可以修改事件或者事件的某个字。每个修饰符前面必须有一个冒号(:)。

替换修饰符  替换修饰符要比其他修饰符复杂。下面的示例演示了替换修饰符纠正前一个事件中的某处错误:

$ car /home/jenny/memo.0507 /home/a1ex/1etter.0507

bash: car: command not found

$ !!:s/car/cat

cat /home/jenny/memo.0507 /home/alex/letter.0507

...

替换修饰符的语法如下:

[g]s/old/new/

old为原字符串(并非正则表达式),new表示代替old的那个字符串。替换修饰符用new替换第1次出现的old。在s前面放上g(像gs/old/new/),将造成全局替换,即将所有出现的old均替换掉。这个示例中用/作为分界符,但可以使用任何不在oldnew中出现的字符。如果最后一个分界符后面紧跟RETURN符,那么这个分界符是可选的。与vim中的替换命令一样,历史机制用old取代了new中的&号。shell将用前一个旧字符串或者在搜索?string?的命令中的字符串来替换空的old字符串(s//new/)。

快速替换  替换修饰符的一个简写形式是快速替换,可用它来重新执行最近事件,同时改变该事件的某些内容。快速替换字符是脱字符(^)。比如,命令:

$ ^oldAn^ew^

与下面的命令的结果相同:

$ !!:s/o1d/new/

因此,如果想在前一个事件中用cat取代car,那么输入如下命令:

$ ^car^cat

cat /home/jenny/memo.0507 /home/alex/letter.0507

...

如果最后那个脱字符后面紧接着一个RETURN符,就可以忽略该脱字符。与其他命令行替换一样,在替换之后shell出现时,它将显示该命令行。

其他修饰符  除替换修饰符外,修饰符还可以对由事件标志符和可选字标志符选取的事件部分进行简单的编辑。可以使用多个修饰符,彼此之间用冒号(:)分开。

下面的命令序列使用ls列出某个文件的名字,然后重复命令而不执行它(p修饰符),接着重复最后一条命令,再次删除路径名最后那部分(h修饰符)而不执行它:

$ ls /etc/sysconfig/harddisks

/etc/sysconfig/harddisks

$ !!:P

ls /etc/sysconfig/harddisks

$ !!:h:p

ls /etc/sysconfig

$

表8-10列出了除替换修饰符之外的事件修饰符。

表8-10  修饰符

修  饰  符

功    能

e(extension)

删掉除文件名扩展之外的所有内容

h(head)

删除路径名的最后部分

p(print-not)

显示命令,但是不要执行

q(quote)

引用该替换,以防止对其进行进一步的替换

r(root)

删除文件名扩展

t(tail)

删掉路径名中除末尾之外的所有元素

x

与q类似,除了单独引用替换中的每个字

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

bzcat         bzdiff        bzip2         bzless

bzcmp         bzgrep        bzip2recover bzmore

$ bz ■

然后,用户输入c并按TAB键两次。shell显示两个以bzc开头的命令。用户输入a,后面跟着TAB,shell补全这条命令,因为此时只有一个命令以bzca开头。

$ bzc —> TAB (beep) —> TAB

bzcat bzcmp

$ bzca —> TAB —>t

(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

dark_passage dark_victory

$ cat films/dark_■

当用户输入足够的信息可区分两个可能的文件并按下TAB键时,bash显示这个唯一的路径名。如果在字符_之后输入p,后面跟着TAB键,那么shell将完成命令行:

$ cat fi1ms/dark_p —> TAB —> assage

因为没有更多的模糊名字,shell附加了一个空格符,这样用户就可以完成命令行,或者按下RETURN键执行该命令。如果完整的路径名是一个目录,bash将在空格符的地方附加一个斜杠符(/)。

(3) 变量补全

当输入变量名时,按下TAB键将会进行变量补全操作,即bash将试图完成该变量的名称。当遇到歧义时,按下TAB键两次将显示可选项的列表:

$ echo $HO —> TAB —> TAB

$HOME      $HOSTNAME $HOSTTYPE

$ echo $HOM —> TAB —> E

 

按下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

" Keystroke_sequence ": 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

kill-whole-line can be invoked via "\C-r".

可以用双引号将文本括起来(只在emacs模式下可用),以绑定该文本:

"QQ": "The Linux Operating System"

使用该命令后,当用户输入QQ时,bash就会插入字符串The Linux Operating System。

(3) 条件结构

使用$if指令可以根据条件选择.inputrc文件的一部分。条件结构的语法如下:

$if [test[=value]]

commands

[$else

commands

$endif

其中,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

set editing-mode vi

$if mode=vi

"\C-y": vi-next-word

$else

"\C-y": forward-word

$endif

因为bash启动的时候读取这个条件结构,所以在.inputrc文件中设置编辑模式。使用set命令交互式地改变模式并不能改变CONTROL+Y的绑定。

要获得更多关于Readline库的信息,请打开bash的man手册页,并输入命令/^READLINE,该命令将在每行起始处搜索字READLINE。

 

如果Readline命令不能运行,请注销并再次登录 

提示

当用户登录的时候,Bourne Again Shell读取~/.inputrc文件。当改变该文件之后,要想测试这些修改,应该首先注销然后再次登录。

查看所有评论(0)条】

最近评论



正在载入评论列表...
热点评论