获取bash中的历史命令的参数

我们在执行shell命令时,往往需要使用之前命令的参数。在参数比较简单时,通过重复输入就能满足需要。在参数比较长或者参数个数比较多时,如果可以重用历史命令中的参数就能达到事半功倍的效果。本文将讨论三种获取历史命令中参数的方法。

1、通过readline快捷键实现

Readline是一个强大的库,用于实现方便的命令行编辑功能,bash、ftp、python、zsh、mysql等程序的命令行界面都是使用readline实现的。事实上,我们经常使用的ctrl-r(查找历史命令)、ctrl-p(上一历史命令)、ctrl-a(跳到行首)等快捷键并不是bash实现的,其幕后功臣正是readline。

通过输入alt-dot(alt键+.键)、esc-dot(ESC键+.键)、meta-dot能够得到上一命令的最后一个参数。虽然通过readline可以得到上一命令的其他参数,但这些快捷键往往与远程登录工具有冲突,需要单独设置TERM类型,因此本文不做介绍,关于这些快捷键可以参考readline shortcuts这里

2、通过$_实现

$_其中保存着上一命令的最后一个参数,跟$$、$?等类似,可以认为是bash的内置变量。利用$_,创建并cd到一个目录可以这样实现:

   1: makedir dir && cd "$_"

$_会进入到历史命令之中,即执行history命令能看到之前输入的$_,这根稍后介绍的bash历史展开有显著的不同。

顺便说一下,在python shell中_也有意义,表示上一个表达式的结果。

3、通过bash历史展开(history expand)实现

使用bash历史展开时用,!$获取上一命令的最后一个参数。bash历史展开由命令、参数、操作符三部分构成,分别表示展开哪一条命令、该命令的哪个参数、对命令的操作。命令展开完成之后才会进入.bash_history中,即执行history命令不会看到用于历史展开的参数。

本节的所有命令都假设当前bash已经有如下的历史:

neoli@ISD32_54_sles10:~/tmp/123$ history
1  2012-09-21 20:54:55 echo 1 2 3 4 5
2  2012-09-21 20:55:08 ls 6 7 8 9 10
3  2012-09-21 20:55:15 echo 11 12 13 14 15
4  2012-09-21 20:55:22 cat 16 17 18 19 20
5  2012-09-21 20:55:27 echo 21 22 23 24 25

1) 命令部分在bash中叫做Event Designators,一般用!开始一个历史展开。

  • !n              表示第n条命令,如!2表示执行ls 6 7 8 9 10
  • !-n            表示倒数第n条命令,如!-3表示执行echo 11 12 13 14 15
  • !!              表示上一条命令,是!-1的快捷方式
  • !string       表示以string开始的最近的一条命令,如!echo表示echo 21 22 23 24 25
  • !?string?    表示含有string的最近的一条命令,如!?6?表示cat 16 17 18 19 20
  • ^string1^string2^ 表示执行上一条命令,并将其中的第一个string1替换为string2,如果string1不存在则替换失败,不会执行命令。
  • !#             表示当前命令现在已经输入的部分,如echo 1 2 !#会执行echo 1 2 echo 1 2

2)参数部分(Word Designators),用于从命令中选取指定的参数,:用于分割命令部分与参数部分。

  • !!:0          表示上一命令的第0个参数,即命令本身,得到的是echo
  • !2:n          表示第2个命令的第n个参数,如!2:2得到的是7
  • !!:^          表示上一命令第1个参数,可进一步简写为!^,与!!:1同义,得到的是21
  • !!:$          表示上一命令的最后一个参数,可进一步简写为!$,得到的是25
  • !!:x-y       表示第x到第y个参数,-y意为0-y,如!-2:3-4得到的是18 19
  • !!:*          表示上一命令的参数部分,可进一步简写为!*,如!!:*得到的是21 22 23 24 25
  • !!:n*        跟!!:n-$同义
  • !!:n-        意为!!:n-$-1,从第n个参数到倒数第二个参数,如!-2:3-得到的是18 19

通过bash历史展开实现创建并cd到目录的方式为:

   1: mkdir dir && cd !#:1

其中!#表示"mkdir dir && cd”,取第一个参数就得到了目录名。

3)操作符(Modifiers),在可选的参数部分之后,可以指定一个或多个用:开始的操作符

  • h  去除最后的一个文件路径部分,假设上一条命令echo /tmp/123/456/,则cd !:1:h:h意为cd /tmp/123;假设上一条命令echo /tmp/123/456,则cd !:1:h:h意为cd /tmp
  • t 去除所有的开始的文件路径部分,假设上一条命令为echo /tmp/123/456/,则cd !:1:t意为cd;假设上一条命令为echo /tmp/123/456,则cd !:1:t意为cd 456
  • r 去除后缀,假设上一条命令为echo /tmp/bbs.c,则echo !:1:r意为echo /tmp/bbs
  • e 得到后缀,假设上一条命令为echo /tmp/bbs.c,则echo !:1:e意为echo .c
  • p print命令而不执行
  • [g]s/string1/sting2/ 将命令的string1替换为string2,g意为全局替换,假设上一条命令为echo 1 2 1,则!:gs/1/3/意为echo 3 2 3。3.1中的^string1^string2^相当于!!:s/string1/string2/
  • [g]& 意为执行上次替换,g意为全局替换。接上例,假设上一条命令为echo 123451,则!:&意为echo 323451

 

参考链接:

[1] http://www.gnu.org/software/bash/manual/bashref.html#History-Interaction

[2] http://stackoverflow.com/questions/4009412/bash-first-argument-of-the-previous-command

posted @ 2012-09-21 22:07  千里快哉  阅读(1520)  评论(0编辑  收藏  举报