9.3 历史扩展
历史库提供了一个历史扩展功能,类似于csh
提供的历史扩展。本节描述了用于操作历史信息的语法。
历史扩展将历史列表中的词引入输入流,使重复命令、将前一个命令的参数插入当前输入行或快速修复前一个命令中的错误变得容易。
历史扩展是在读完一整行后立即进行的,在shell将其分解成字之前,并在每一行单独进行。Bash试图通知历史扩展函数关于前几行的引号仍然有效。
历史扩展分两部分进行。第一部分是确定在替换过程中应该使用历史列表中的哪一行。 第二部分是选择该行的部分内容以纳入当前的历史列表中。从历史中选择的行被称为event,而该行中被操作的部分被称为word。各种修改器可以用来操作所选的字。该行以Bash的方式被分割成单词,因此被引号包围的几个单词被认为是一个单词。 历史扩展是由历史扩展字符的出现引入的,默认为‘!’。
历史扩展实现了类似于shell的引用约定:反斜杠可以用来消除对下一个字符的特殊处理;单引号包围了逐字序列的字符,可以用来抑制历史扩展;双引号内的字符可能会受到历史扩展的影响,因为反斜杠可以摆脱历史扩展的字符,但单引号可能不会,因为它们在双引号内没有被特殊处理。
当使用shell时,只有‘\’和‘'’可以用来转义历史扩展字符,但如果历史扩展字符紧接在双引号字符串的结束双引号之前,也会被当作引号处理。
几个可由shopt
内置程序设置的shell选项(见2 Shopt 内置程序)可用于调整历史扩展的行为。如果启用histverify
shell选项,并且使用Readline,历史替换不会立即传递给shell解析器。 相反,扩展的行会被重新加载到Readline编辑缓冲区以进一步修改。 如果使用Readline,并且启用histreedit
shell选项,失败的历史扩展会被重新加载到Readline编辑缓冲区以进行修正。history
内置命令的-p选项可用于在使用前查看历史扩展的效果。 history
内置命令的-s选项可用于将命令添加到历史列表的末尾,而不实际执行,这样它们就可以在以后调用。 这在与Readline配合时最有用。
shell允许用histchars
变量控制历史扩展机制所使用的各种字符,如上所述(见5.2 Bash 变量)。shell在写历史文件时使用历史注释字符来标记历史时间戳。
1 事件代号
事件代号是对历史列表中的命令行条目的引用。 除非引用是绝对的,否则事件是相对于历史列表中的当前位置而言的。
!
开始一个历史替换,除非后面有空格、制表符、行尾、‘=’或‘(’(当使用
shopt
内置的extglob
shell选项被启用时)。!n
请参考命令行n。
!-n
参照后面n的命令。
!!
请参考前面的命令。这是‘!-1’的同义词。
!string
参考历史列表中以string开头的当前位置之前的最新命令。
!?string[?]
参考历史列表中包含string的当前位置之前的最新命令。 如果string后面紧跟换行,则可以省略尾部的‘?’。 如果缺少string,则使用最近一次搜索的字符串;如果没有之前的搜索字符串,则是一个错误。
^string1^string2^
快速替换。重复上一条命令,将string1替换为string2。相当于
!!:s^string1^string2^
。!#
到目前为止,输入的整个命令行。
2 词代号
词代号用于从事件中选择所需的词语。 一个‘:’将事件规范与词语代号分开。如果词语代号以‘^’、‘$’、‘*’、‘-’或‘%’开头,可以省略。字数从行首开始编号,第一个字用0(零)表示。字词被插入到当前行中,并以单个空格分隔。
例如:
!!
指定前面的命令。当你输入时,前面的命令会全部重复。
!!:$
指定前一个命令的最后一个参数。这可以缩短为
!$
。!fi:2
指定最近一条以字母
fi
开头的命令的第二个参数。
这里是单词的代号。
0 (zero)
第
0
个词。对于许多应用来说,这就是命令字。n
n第1个词。
^
第一个参数;也就是字1。
$
最后一个参数。
%
最近一次‘?string?’搜索所匹配的第一个单词,如果搜索字符串以属于一个单词的字符开始的话。
x-y
一系列单词;‘-y’是‘0-y’的缩写。
*
所有单词,除了第
0
个。这是‘1-$’的同义词。 如果事件中只有一个词,使用‘*’并不是错误;在这种情况下会返回空字符串。x*
缩写为‘x-$&rsquo。
x-
缩写‘x-$’,就像‘x*’,但省略最后一个字。 如果缺少‘x’,它默认为0。
如果提供了一个词的代号,但没有事件说明,则使用前一个命令作为事件。
3 修饰符
在可选的词的代号之后,你可以添加一个或多个下列修饰语的序列,每个修饰语前面都有一个‘:’。 这些修饰语,或编辑从历史事件中选择的一个或多个词。
h
删除尾随的路径名部分,只留下头部。
t
删除所有前导路径名组件,留下尾部。
r
删除形式为‘.suffix’的尾部后缀,留下基本名称。
e
删除除尾随后缀之外的所有内容。
p
打印新命令但不执行它。
q
引述被替换的词语,避免进一步的替换。
x
与‘q’一样,引用被替换的单词,但在空格、制表符和换行处断开单词。 ‘q’和‘x’修改器是相互排斥的;使用最后一个提供的修改器。
s/old/new/
用new 替换事件行中第一次出现的old。任何字符都可以用作分隔符来代替 ‘/’。分隔符可以在 old 和 new 中用单个反斜杠引用。如果‘&’出现在new,被old取代。单个反斜杠将引用 ‘&’。如果 old 为 null,则将其设置为最后一个被替换的 old,或者,如果之前没有发生历史替换,则设置为最后一个 string !?string
[?]
搜索。如果 new 为 null,则删除每个匹配的 old。如果最后一个分隔符是输入行的最后一个字符,则它是可选的。&
重复前面的替换方法。
g
a
导致变化应用于整个事件行。与‘s’一起使用,如
gs/old/new/
,或与‘&’ 一起使用。G
对事件中的每个词应用以下‘s’或‘&’修饰语一次。