9.历史的交互使用
本章从用户的角度介绍了如何使用 GNU 的历史库功能。可以把这里的内容作为用户指南。
关于如何在其它程序中使用 GNU 的历史库功能,请参考《GNU Readline 库参考手册》

9.1 Bash的历史功能
如果使用了内部命令 set 的“-o history”选项,shell 就会允许访问历史命令,即以前输入的命令。
shell变量 HISTSIZE 控制历史中所保存命令的数目,即只保存最后 $HISTSIZE条(默认是 500)命令的文本。
根据 shell 变量 HISTIGNORE 和 HISTCONTROL 的值,shell 会在进行参数和变量扩展之前及历史扩展之后把每条命令保存在历史中。
shell在启动时会用 HISTFILE 变量指定的文件(默认是 ~/.bash_history)对历史进行初始化。
如果有必要,就截断 HISTFILE 变量指定的文件,使它包含的行数不超过 HISTFILESIZE 变量的值。
在交互式的shell退出运行时,把历史中最后 HISTSIZE 行复制到 HISTFILE 变量指定的文件中。
如果设置了 shell 选项 histappend,则把这些行附加到历史文件中,否则就覆盖历史文件。
如果重置了 HISTFILE,或者历史文件不可写,则不保存历史。
保存了历史以后,就把历史文件截断到不超过 $HISTFILESIZE 行。如果没有设置 HISTFILESIZE 则不截断历史文件。
如果设置了 HISTTIMEFORMAT,则把与每条历史关联的时间戳信息也一并写入到历史文件中,时间信息用历史注释字符标志。
在读取历史文件时,以历史注释字符和紧跟其后的数字开头的行会被当作下一条命令的时间戳。
可以用内部命令 fc 来列出、编辑和重新执行部分历史;也可以用内部命令 history 显示和修改历史,或者操纵历史文件。
在进行命令行编辑时,每种编辑模式中都有搜索命令来访问历史。
shell可以控制在历史文件中保存哪些命令。HISTCONTROL 和 HISTIGNORE 变量可以保存或忽略输入命令中的一部分条目。
如果设置了 shell 选项 cmdhist,shell 就会试图在同一条目中保存多行命令的每一行,必要时可能会加上分号以保证语法的正确性。
shell选项 lithist 会使 shell 用行内的换行符,而不是分号。
可以用 shopt 来设置这些选项。

9.2 Bash历史内部命令
Bash提供了两个命令来操纵历史和历史文件。
A.fc 改变命令
语法一:fc [-e 编辑器] [-lnr] [第一个] [最后一个]
功能:将从历史文件中选取从第一个到最后一个之间的命令。
第一个和最后一个都可以是字符串(用来指定最近用这些字符开头的命令)或数字(历史中的位置索引;负数表示从当前命令开始索引)。
如果没有指定最后一个,它就和第一个相同;如果没有指定第一个,则在编辑时它就是前一个命令,在列表时就是 -16。
如果指定了“-l”选项助记词: List, 列表,就在标准输出中列出这些命令;“-n”选项助记词: Number, 行号,可以在列出命令时不显示行号;而“-r”选项助记词: Reverse, 倒序,使列表倒序排列。
如果没有指定了“-l”选项,则启动编辑器并打开包含这些命令的文件。
如果没有指定编辑器就使用变量 ${FCEDIT:-${EDITOR:-vi}} 扩展后的值;即,如果设置了 FCEDIT 变量就使用它,或者如果设置了 EDITOR 变量就使用它,如果都没有设置就用vi。
编辑结束以后则显示并执行编辑过的命令。
语法二:fc -s [模式=替换文本] [命令]
功能:把每个选中的命令中与模式匹配的文本改成替换文本后执行。
fc 命令很有用的别名是 r='fc -s',这样输入“r cc”就会执行最后一个以 cc 开头的命令,而输入“r”就会执行杌后一个命令。
B.history
history [n] 只列出最后 n行。
history -c
history -d 偏移量
history [-anrw] [文件名]
history -ps 参数
如果没有选项,列出历史和行号。前面带有"*"的行已经被修改过。
如果设置了 shell 变量 HISTTIMEFORMAT 且不为空,就用它作为 strftime 的参数来显示每条历史所关联的时间戳。
在格式化的时间戳和历史行之间没有空白,所以如果想把时间戳和历史行之间用空白分隔,必须在 HISTTIMEFORMAT 的后面显式指定这些空白。
如果指定了选项,就会有下面的含义:
-c 清除历史。可以把它和其它选项乹起使用来完全替换历史。助记词: Clear, 清除
-d 偏移量 删除偏移量处的历史行。偏移量应该是列出历史时显示的数值。助记词: Delete, 删除
-a 把新的历史行(即当前的 Bash会话开始后输入的历史行)附加到历史文件中。助记词: Append, 附加
-n 把历史中尚未读取的行附加到当前的历史中。这些行是当前的 Bash会话开始后附加到历史文件中去 的。助记词: New, 新行
-r 读取历史文件,把其内容附加到当前的历史中。助记词: Read, 读取
-w 把当前的历史写入到历史文件中。助记词: Write, 写入
-p 对参数进行历史扩展并在标准输出上显示其结果,而不是把结果存放在历史中。助记词: outPut, 输出
-s 把参数作为单个条目附加到历史中。助记词: Single, 单个
如果使用了"-w"、"-r"、"-a"、"-n"选项中的任意一个并且给定了文件名,就把文件名当作历史文件。 如果没有给定文件名,则使用 "HISTFILE"变量的值。

9.3 历史扩展
历史库提供了类似于 csh 中的历史扩展功能。本节介绍操纵历史信息的语法。
历史扩展把历史中的单词引入到输入流中,这样易于重复输入命令、在当前输入行中插入以前命令的参数、或者快速修改以前命令中的错误。
历史扩展有两个步骤:第一步决定在替换时应该使用历史中的哪一行,第二步选择选定行的部分文本以包含到当前行中。
从历史中选定的行叫做"条目";该行中要操纵的文本部分叫"单词",可以使用各种修饰符来控制选中的单词。
与 Bash一样,选中的行被拆分成单词;被引用的多个单词当作一个单词。
历史扩展由历史扩展字符(默认是"!")引入。只有"\"和"'"可以对历史扩展字符转义。
可以用内部命令 shopt 设置 shell 选项来调整历史扩展的行为。
如果设置了shell选项histverify,并且使用了Readline,则历史扩展不会立即传给 shell 解释器,而是把扩展后的命令行重新加载到 Readline 的编辑缓存中以备进一步修改。
如果使用了Readline并且设置了shell选项histreedit,则历史扩展失败时将重新加载到 Readline 的编辑缓存中以备更正。
在进行历史扩展之间,可以用内部命令 history 的"-p"选项来查看历史扩展如何进行。
而内部命令 history 的"-s"选项可以用来把命令直接加入到历史文件中,这样它就可以在以后使用。这如果和 Readline 一起使用将会非常有用。
shell可以通过 histchars 变量控制历史扩展机制所使用的各种字符,还可以在写入历史文件时用历史注释字符来标志历史中的时间戳。

9.3.1 条目指示符
条目指示符指向历史中的命令行。
! 开始历史替换,除非后面跟着空格、制表符、行结束符、"="、或"(" (如果用内部命令 shopt 打当了extglob 选项)。
!n 选择命令行n。
!-n 选择向后第n行命令。
!! 选择前一条命令,它和"!-1"是等价的。
!字符串 选择最近以“字符串”开头的命令。
!?字符串[? 选择最近包含字符串的命令。如果字符串后面紧跟着换行符就可以省略结尾的"?"。
^字符串一^字符串二^ 快速替换。重复最后的命令,并把字符串一替换成字符串二;它和 !!:s/字符串一/字符串二 是等价的。
!# 目前已经输入的整个命令。

9.3.2 单词指示符
单词指示符用来从选定条目中选择指定的单词。
条目指示符和单词指示符之间用":"分隔;如果单词指示符以"^"、"$"、"*"、"-"、"%"开头,则可以省略分隔符。
单词从行首开始数起,第一单词序号为 0。插入到当前行中时,这些单词用空格分开。
例如,
!! 指定前一条命令。如果输入这个指示符则整个重复前一条命令。
!!:$ 指定前一条命令的最后一个参数;可以简写为 !$。
!fi:2 指定最近以字母 fi 开头的命令的第二个参数。
下面是单词指示符:
0 即零,第零个单词。对大多数命令而 ,它是指命令名。
n 第 n 个单词。
^ 第一个参数(单词)。
$ 最后一个参数。
% 最近"?字符串?"匹配的单词。
x-y 单词范围。"0-y"可以简写为"-y"。
* 除了第零个以外的所有单词,和"1-$"同义。如果条目中只有一个单词,使用"*"也不会出错,而是返回空字符串。
x* "x-$"的简写形式。
x- 和"x*"一样,是"x-$"的简写形式,但是忽略来后一个单词。
如果使用单词指示符时没有用条目指示符,则把前一条命令作为条目。

9.3.3 修饰符
在可选的单词指示符后面,可以加上下列一个或多个修饰符,每个修饰符前都有":"。
h 去掉文件名的尾部,只保留头部。
t 去掉文件名的头部,只保留尾头部。
r 去掉结尾的扩展名,只保留文件基名。
e 去掉扩展名以外的所有部分。
p 打印新的命令但不执行。
q 引用替换后的单词,以备进仛步替换。
x 和"q"丢样引用替换后的单词,同时还在空格、制表符、换行符的地方把单词分开。
s/旧词/新词/ 把条目中的第一个旧词替换成新词。在"/"的地方可以使用任何分隔符。
在旧词和新词中要用到分隔符的地方可以用一个反斜杠对分隔符转义。
如果新词中出现"&",就替换成旧词;可以使用一个反斜杠来引用"&"。
结尾的分隔符如果是输入行的最后一个字符则是可选的。
& 重复上次替换。
g 使替换在整个条目中进行,和“s"一起使用,例如 gs/old/new/,或者和"&"一起使用。
G 对条目中的每个单词都执行一次"s"修饰符。

posted on 2019-11-14 16:41  Brad Miller  阅读(162)  评论(0编辑  收藏  举报