Jef*_*ves 11 command-line bash command-history
题
假设我刚刚输入此命令来计算包含特定字符串的行数:
me@machine $ command-producing-multi-line-output | grep -i "needle" | wc -l
Run Code Online (Sandbox Code Playgroud)
现在我怎么能快速"needle"
用其他词代替?
当前低效的解决方案
现在我:
Up
键盘以加载最后一个命令。Left
或Ctrl
+Left
直到到达"needle"
。Backspace
或Ctrl
+w
删除单词。Enter
。这似乎非常低效。
尝试的非工作解决方案
我试图研究历史捷径,如!!:sg/needle/new-needle
;但这有几个问题:
Up
把!!:sg/needle/new-needle
后面的命令行上。这样做只会显示它扩展到的内容(直接回到原始问题)。needle
和new-needle
(即!!:sg/new-needle-from-before/yet-another-new-needle
)。needle
而不是使用类似!:4
或$4
(即!!:sg/!:4/new-needle
或!!:sg/$4/new-needle
)之类的东西来节省时间/击键。我也发现了类似!:^-3 "new-needle" !:5-$
但也有问题的东西:
我相信必须有一些超快速的方法来做我想做的事情,而且那里的一些 linux 专家知道这一点。如果您对此有任何意见或建议,我将不胜感激。
编辑:
背景
只是一点背景知识,我在命令行上使用 OpenStack 进行了很多工作,我发现自己经常需要在管道命令的长命令链中的多个位置替换参数。
我们的 OpenStack 环境的配置方式,多个工程师stack
在任意数量的服务器上共享一个用户,并且在多个环境中有多个集群。所以在.bashrc
or.profile
文件中声明的函数实际上是不可能的。
我希望有一些便携式的东西可以快速使用,不需要或只需要很少的设置。否则,我可能只需要完全在外壳之外使用解决方案(例如 AutoHotKey/Keyboard Maestro/AutoKey 中的剪贴板替换等)。
mos*_*svy 11
这究竟是什么历史扩展是:
$ command-producing-multi-line-output | grep -i "needle" | wc -l
...
$ ^needle^nipple
command-producing-multi-line-output | grep -i "nipple" | wc -l
...
Run Code Online (Sandbox Code Playgroud)
Jef*_*ler 10
我遇到了类似的情况,并在这里提出我的解决方案,以防万一它是一个有用的模式。
一旦我意识到我正在反复更改一段令人讨厌的数据以交互方式替换,我将停下来写一个while
小循环:
$ command-producing-multi-line-output | grep -i "needle" | wc -l
0
$ command-producing-multi-line-output | grep -i "haystack" | wc -l
0
$ while read needle; do
Run Code Online (Sandbox Code Playgroud)
Up-Arrow到上command-producing-multi-line-output
一行并替换"haystack"
为"$needle"
command-producing-multi-line-output | grep -i "$needle" | wc -l; done
something
0
something else
0
gold
1
Run Code Online (Sandbox Code Playgroud)
(以Control+结尾D)
或者稍微更高级的变体:
$ while read needle; do
printf 'For: %s\n' "$needle"
command-producing-multi-line-output | grep -i "$needle" | wc -l; done
Run Code Online (Sandbox Code Playgroud)
如果我看到这个命令行超越“今天”的未来,我会把它写成一个函数或脚本。
一个有用的别名bash
是
alias r='fc -s'
Run Code Online (Sandbox Code Playgroud)
r
默认情况下,该命令通常在其他 shell 中找到1,并重复历史记录中最近的命令。该bash
手册甚至将其称为定义的有用别名:
[...] A useful alias to use with this is ``r="fc -s"'',
so that typing ``r cc'' runs the last command beginning with
``cc'' and typing ``r'' re-executes the last command.
Run Code Online (Sandbox Code Playgroud)
它还允许您在最后一个命令的文本中进行替换。
在这里,我正在运行您的命令,然后我使用上面的别名将单词替换needle
为单词haystack
:
alias r='fc -s'
Run Code Online (Sandbox Code Playgroud)
[...] A useful alias to use with this is ``r="fc -s"'',
so that typing ``r cc'' runs the last command beginning with
``cc'' and typing ``r'' re-executes the last command.
Run Code Online (Sandbox Code Playgroud)
当我r needle=haystack
在命令行上使用时,shell 会打印出它要运行的命令,然后立即运行它。如您所见,它也替换了这个词。
错误显然是由于我没有command-producing-multi-line-output
命令造成的,但这在本练习中并不重要。
该fc
命令不会保存到您的历史记录中,但您可以通过将其创建为 shell 函数来保存它,如下所示:
$ command-producing-multi-line-output | grep -i "needle" | wc -l
bash: command-producing-multi-line-output: command not found
0
Run Code Online (Sandbox Code Playgroud)
然后你可以做
$ r needle=haystack
command-producing-multi-line-output | grep -i "haystack" | wc -l
bash: command-producing-multi-line-output: command not found
0
Run Code Online (Sandbox Code Playgroud)
重新运行最近的命令,comm
并needle
使用r needle=haystack comm
以下命令替换:
fc() {
command fc "$@"
history -s fc "$@" # append the given fc command to history
}
Run Code Online (Sandbox Code Playgroud)
重新运行最近的命令,但haystack
使用r haystack=beeswax
以下命令替换:
$ command-producing-multi-line-output | grep -i "needle" | wc -l
bash: command-producing-multi-line-output: command not found
0
Run Code Online (Sandbox Code Playgroud)
请注意fc
在最后一行中进行的双重调用,首先通过我们的别名r
,然后通过我们的函数fc
。
显然,将fc
命令保存到历史记录会使您冒着意外fc -s
递归调用的风险。
1在zsh
它是一个内置的命令,OpenBSD中ksh
它是一个默认的别名fc -s
,在ksh93
它的默认别名hist -s
等。
OP 说在 in.bashrc
中声明的函数不实用,但没有什么可以阻止以交互方式声明一个函数。由于这仅适用于当前会话,因此可以使用单个字母名称,例如q
.
从...开始
$ command-producing-multi-line-output | grep -i "haystack" | wc -l
Run Code Online (Sandbox Code Playgroud)
按Up ;}结束一个函数,编辑haystack
to $1
, Control+aq(){Space得到
q(){ command-producing-multi-line-output | grep -i "$1" | wc -l;}
Run Code Online (Sandbox Code Playgroud)
那么你可以使用q needle
, q haystack
, q something
。我更喜欢while
当前接受的答案中的解决方案,因为它允许在搜索/计数之间使用其他命令。
对于这种特殊情况,我实际上会定义
q(){ command-producing-multi-line-output | grep -i "$@";}
Run Code Online (Sandbox Code Playgroud)
因为我可能希望在某个阶段看到实际匹配的线条,所以我可以使用q needle | wc -l
或更好q -c needle
地计数,并q needle
查看线条。
由于函数定义将存储在 bash 历史记录中,如果在以后的会话中需要,通常可以重新加载定义。