Bash 历史非常悠久,懂的怎样使用它的拓展历史将会让你在Linux命令行的使用上极具创造性。
这篇文章解释了15个使用Bash的例子:
实践指示符----指历史的特别命令 以 !开始。
单词指示符----指特定的历史入口。这个even指示符和word指示符都被空格分开
修饰符----修饰event或word描述符的结果
这篇文章是我的正在编写的Bash Tutorial Series的一部分
正如你所知道的,查看历史记录,使用history命令。通常会战士所有被早期执行的命令在下面的表中。
$ history
1 tar cvf etc.tar /etc/
2 cp /etc/passwd /backup
3 ps -ef | grep http
4 service sshd restart
5 /usr/local/apache2/bin/apachectl restart
Bash 的历史事件修饰符
1. 从history列表中执行特定的命令 用 !n (n 为行号)
如果你之前已经执行过某个命令,你不必重新输入这个命令,可以直接用history列表中显示的此命令行号来执行它。
例如,执行命令#4,按照下列的方式做
$ !4
service sshd restart
执行刚刚执行的命令之前的那个命令,这样作
$ !-2
执行刚刚执行的命令
$ !!
$ !-1
你也可以按下 <ctrl>-P (如果你在默认的emacs模式中)进入之前的命令
如果你使用的是vi风格的编辑方式,可以通过使用 'set -o vi',用<Esc > -k 进入之前的命令。
2.执行键盘输入命令使用 !字符串 和 !?字符串
你也可以用键盘去执行history列表中已经执行过的命令。
接下来的例子将会搜索之前的以'ps'开头的命令 并执行它。
$ !ps
ps -ef | grep http
接下来的例子会搜索之前的 含有 “apache”关键字的命令并执行它。在这个例子中,它会查找之前的“/usr/local/apache2/bin/apachectl restart”
并执行它。
$ !?apache
/usr/local/apache2/bin/apachectl restart
3.从之前的命令中替换字符从使用 ^str1^str2
在接下来的例子中,我们首先会执行ls 命令来验证一个文件。今后我们将会意识到我们想去查看文件的内容。接下来我们不是
打印整个命令,而是用cat 来替换ls ,如下所示
$ ls /etc/cron.daily/logrotate
$ ^ls^cat^
cat /etc/cron.daily/logrotate
注意:想要了解更多的关于history的使用技巧,可以参照15掌握history命令行的例子。这个解释了怎么样显示时间绰,
怎样使用各种各样的历史相关环境变量包括 HISTTIMEFORMAT ,HISTSIZE,HISTFILE,HISTCONTROL,还用HISTIGNORE
Bash History Word Designators
在你打印新命令的时候单词指示符是非常有用的,除了使用上一个命令执行过程中的参数。下面是一些例子
4.获得上一个命令的参数用 :^
接下来的例子,“!cp:^”用来作为 “ls -al”的参数。“!cp:^”定位之前命令中以“cp”开头的命令,并获得其第一个参数
$ cp /etc/passwd /backup
$ ls -l !cp:^
ls -l /etc/passwd
下面的例子获得上一个命令的第一个参数
$ ls -l !!:^
5。获得一个命令最后的最后一个参数:$
接下来的例子中 “!cp:$”作为ls -al的一个参数,其定位之前命令的在history列表中以“cp”开头并获得其最后一个参数。
$ cp /etc/passwd /backup
$ ls -l !cp:$
ls -l /backup
接下来的例子获得前一个命令的最后一个参数
$ls -l !!:$
6。获得地n个参数使用:n
接下来的例子中 “!tar:2” 用来作为ls -l 命令的参数 ,其定位之前命令的跌入个参数
$ tar cvfz /backup/home-dir-backup.tar.gz /home
$ ls -l !tar:2
ls -l /backup/home-dir-backup.tar.gz
7。获得命令的所用参数用:*
接下来的例子中“!cp:*”用来作为ls -l 的参数,其定位之前命令中以cp开始的命令并获得其所有参数。
$ cp /etc/passwd /backup
$ ls -l !cp:*
ls -l /etc/passwd /backup
8。引用最近搜索的单词用 !%
正如我们上面所阐述的,“!?apche”会搜索之前的命令中含有apache关键词的命令并执行它。
$ /usr/local/apache2/bin/apachectl restart
$ !?apache
/usr/local/apache2/bin/apachectl restart
!%将指向之前?搜索到的整个词组或单词。
例如,如果你之前的搜索 “?apache” ,那么“!%”将会匹配“/usr/local/apache2/bin/apachectl”.注意,这里的“/”被认为是这
句话的一部分。
所以,这种情况下,执行下面的,你可以停止apache.
$ !% stop
/usr/local/apache2/bin/apachectl stop
9。获取一定范围的参数使用 x-y
接下来的例子中,“!tar:3-5”作为ls -l的参数,“!tar:3-5”定位之前命令中以"tar"开头的命令并获得其第3-5之间的参数
$ tar cvf home-dir.tar john jason ramesh rita
$ ls -l !tar:3-5
ls -l john jason ramesh
下面的例子获得所有的参数(从2开始)
$ ls -l !tar:2-$
请注意下面的内容:
!!:*获得之前命令的所有参数。
!!:2*获得从第二个开始的所有参数。
!!:2-$ 和上面的一样。获得从第二个开始的所有参数。
!!:2- 获得所有参数,从第二个开始(除了最后一个参数)
Bash History Modifiers
修饰符在单词指示符之后,解释如下:
10。去除路径后的文件名使用:h
接下来的例子中,“!!:$:h”获得之前命令的最后一个参数,明且取出路径明,这种情况下,它去除文件名,就得到了路径名
$ ls -l /very/long/path/name/file-name.txt
$ ls -l !!:$:h
ls -l /very/long/path/name
11。去除所有的引导路径明从单词中使用:t
这个显然的是之前例子的对立
接下来的例子中,“!!:$:t”获得之前命令的最后一个参数,去除所有引导路径名,只得到文件名。
$ ls -l /very/long/path/name/file-name.txt
$ ls -l !!:$:t
ls -l file-name.txt
12。去除文件扩展名用:r
接下来的例子中,“!!:$:r”获得上一个命令的最后一个参数,并且去除.suffix (文件扩展名),这种情况下,其去掉的是.txt
$ ls -l /very/long/path/name/file-name.txt
$ ls -l !!:$:r
ls -l /very/long/path/name/file-name
13。sed 就像substitution 在bash history 用 :s/str1/str2/
不是使用^original^replacement^ 我们之前所讨论的,我们也可以用sed like substitution 在bash 的历史中。这个可能容易记忆
!!调用之前的命令,“:s/original-string/replacement-string/”是sed-like语法替换字符串
$ !!:s/ls -l/cat/
你也可以使用 g 标记,作为全局替换,如下所示。这个在你大错单词想全局替换的时候非常有用。
接下来的例子中,我使用了password 两次而不是passwd
$ cp /etc/password /backup/password.bak
解决他,用全局历史sed like substitution.
$ !!:gs/password/passwd/
cp /etc/passwd /backup/passwd.bak
14。重复替换用:&
如果你已经成功执行了bash历史替换,如上所示,你可以重复同样的替换使用:&
我我错误的输入了"password"而不是“passwd”在另一个
$ tar cvf password.tar /etc/password
现在,替换重新输入命令,或者 “gs/password/passwd”, 我仅仅使用:& 重用上一次的替换。使用":g&" 来使用上一次的
全局替换。
$ !!:g&
tar cvf passwd.tar /etc/passwd
15。打印命令而不执行使用 :p
当你作复杂命令替换的时候或者你想查看最后的命令在执行之前,这个是非常有用的。
接下来的例子中,“!tar:3-:p”,并没有真正的执行命令。
既然我们给出了:; 他只是作一些替换展示新的命令,一旦你已经验证过,bash历史的拓展,并且如果你想这个命令你打算
执行,去除:p 再一次执行他。
$ tar cvf home-dir.tar john jason ramesh rita
$ tar cvfz new-file.tar !tar:3-:p
tar cvfz new-file.tar john jason ramesh