您所在的位置: 首页>>读书频道>>操作系统>>Linux>>

8.5.3 Readline库

http://book.51cto.com  2008-05-15 15:59  Mark G. Sobell 著 杨明军等译  清华大学出版社  我要评论(0)
  • 摘要:《Linux命令、编辑器与Shell编程》第8章内容扩充了第5章描述的shell的交互特性,解释了如何创建和运行简单的shell脚本,讨论如何进行作业控制,介绍shell编程的基本方面,讨论命令历史和别名,同时还描述了命令行扩展。本节说的是 Readline库。
  • 标签:Readline  Bourne Shell  Linux命令、编辑器与Shell编程

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以使Readlinevi模式下启动;设置为emacs以使Readlineemacs模式下启动(默认);类似于shell命令set -o viset -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文件。当改变该文件之后,要想测试这些修改,应该首先注销然后再次登录。

【责任编辑:董书 TEL:(010)68476606】

回书目   上一节   下一节
深入Vista应用程序开发
Ruby on Rails 社区网站开发
ASP.NET从入门到精通
Java完全自学宝典
JavaScript完全自学宝典
 
 验证码: (点击刷新验证码)   匿名发表
  • Visual C++ 完全自学宝典

  • 作者:强锋科技,朱洪波
  • Visual C++ 6.0是微软公司为程序人员提供的Visual Studio 6.0工具套件中的重要组成部分。本书由浅入深地介绍使用Visual C++ 6.0..
Copyright©2005-2008 51CTO.COM 版权所有