大多数 Bash 历史命令快捷方式指南都详尽地列出了所有可用的快捷方式。问题在于,我会使用一次快捷方式,然后在尝试所有可能性时变得茫然。然后我会继续我的工作日,完全忘记它们,只保留了我刚开始使用 Bash 时学到的众所周知的 !! 技巧。
所以它们中的大多数从未被记住。
本文概述了我每天实际使用的快捷方式。它基于我的书《Learn Bash the hard way》的部分内容;(您可以阅读预览来了解更多信息)。
当人们看到我使用这些快捷方式时,他们经常问我:“你刚才做了什么!?” 这只需要最少的努力或智力,但要真正学会它们,我建议每天使用一个,持续一周,然后再学习下一个。花时间让它们在你的手指下熟练掌握是值得的,因为从长远来看,你节省的时间将是巨大的。
1. “最后一个参数”快捷方式:!$
如果你只从本文中学习一个快捷方式,那就学习这个。它将最后一条命令的最后一个参数替换到你的行中。
考虑以下场景
$ mv /path/to/wrongfile /some/other/place
mv: cannot stat '/path/to/wrongfile': No such file or directory
啊,我在命令中放了wrongfile文件名。我应该放 rightfile 才对。
你可能会决定重新输入最后一条命令,并将 wrongfile 完全替换为 rightfile。相反,你可以输入
$ mv /path/to/rightfile !$
mv /path/to/rightfile /some/other/place
命令就会工作。
在 Bash 中,还有其他方法可以通过快捷方式实现相同的效果,但重用最后一条命令的最后一个参数的技巧是我最常用的技巧之一。
2. “第n个参数”快捷方式:!:2
有没有做过类似的事情?
$ tar -cvf afolder afolder.tar
tar: failed to open
像许多其他人一样,我经常搞错 tar(和 ln)的参数,次数多到我都不想承认。

当你像那样混淆参数时,你可以运行
$ !:0 !:1 !:3 !:2
tar -cvf afolder.tar afolder
你的声誉就会被挽救。
最后一条命令的项目是零索引的,可以用 !: 后的数字替换。
显然,你也可以使用它来重用最后一条命令中的特定参数,而不是全部参数。
3. “所有参数”快捷方式:!:1-$
想象一下,我运行一个像这样的命令
$ grep '(ping|pong)' afile
参数是正确的;但是,我想在文件中匹配 ping 或 pong,但我使用了 grep 而不是 egrep。
我开始输入 egrep,但我不想重新输入其他参数。所以我可以使用 !:1$ 快捷方式来请求前一条命令的所有参数,从第二个参数(记住它们是零索引的)到最后一个参数(用 $ 符号表示)。
$ egrep !:1-$
egrep '(ping|pong)' afile
ping
你不必选择 1-$;你可以选择一个子集,例如 1-2 或 3-9(如果前一条命令中有那么多参数)。
4. “倒数第n个”快捷方式:!-2:$
当我知道如何立即纠正我的最后一条命令时,上面的快捷方式非常棒,但通常我在原始命令之后运行命令,这意味着最后一条命令不再是我想要引用的命令。
例如,使用之前的 mv 示例,如果我在犯错后使用 ls 检查文件夹的内容
$ mv /path/to/wrongfile /some/other/place
mv: cannot stat '/path/to/wrongfile': No such file or directory
$ ls /path/to/
rightfile
我就不能再使用 !$ 快捷方式了。
在这些情况下,我可以在 ! 后插入 -n: (其中 n 是历史记录中要回溯的命令数),以从较旧的命令中获取最后一个参数
$ mv /path/to/rightfile !-2:$
mv /path/to/rightfile /some/other/place
同样,一旦你学会了它,你可能会惊讶于你有多频繁地需要它。
5. “获取文件夹”快捷方式:!$:h
这个快捷方式表面上看起来不太有前途,但我每天都会使用它数十次。
想象一下,我运行一个像这样的命令
$ tar -cvf system.tar /etc/system
tar: /etc/system: Cannot stat: No such file or directory
tar: Error exit delayed from previous errors.
我可能想做的第一件事是进入 /etc 文件夹,看看里面有什么,并弄清楚我做错了什么。
我可以通过以下方式一蹴而就地做到这一点
$ cd !$:h
cd /etc
这个快捷方式的意思是:“获取最后一条命令的最后一个参数 (/etc/system),并去掉它的最后一个文件名组件,只留下 /etc。”
6. “当前行”快捷方式:!#:1
多年来,我偶尔会想,我是否可以引用当前行上的参数,直到最终查阅并学习它。我真希望我早点这样做。我最常使用它来制作备份文件
$ cp /path/to/some/file !#:1.bak
cp /path/to/some/file /path/to/some/file.bak
一旦熟练掌握,它就可以成为 … 的非常快速的替代方案
7. “搜索和替换”快捷方式:!!:gs
这个快捷方式在引用的命令中搜索,并将前两个 / 字符中的内容替换为后两个字符中的内容。
假设我想告诉全世界我的 s 键坏了,输出的是 f 而不是 s
$ echo my f key doef not work
my f key doef not work
然后我意识到我只是不小心按到了 f 键。要将所有 f 替换为 s,我可以输入
$ !!:gs/f /s /
echo my s key does not work
my s key does not work
它不仅适用于单个字符;我也可以替换单词或句子
$ !!:gs/does/did/
echo my s key did not work
my s key did not work
测试一下
只是为了向你展示如何组合这些快捷方式,你能弄清楚这些脚趾甲屑会输出什么吗?
$ ping !#:0:gs/i/o
$ vi /tmp/!:0.txt
$ ls !$:h
$ cd !-2:h
$ touch !$!-3:$ !! !$.txt
$ cat !:1-$
结论
对于日常命令行用户来说,Bash 可以是一个优雅的快捷方式来源。虽然有成千上万的技巧和窍门可以学习,但这些是我经常使用的最喜欢的技巧和窍门。
如果你想更深入地了解 Bash 可以教给你的所有知识,请购买我的书《Learn Bash the hard way》或查看我的在线课程《Master the Bash shell》。
本文最初发布在 Ian 的博客 Zwischenzugs.com 上,并已获得许可重复使用。
12 条评论