在终端中使用fzf获取输出而无需执行

10

fzf非常好用!我想使用它来搜索bash历史记录。当找到匹配项时,我希望将其放置在命令行上,但不要立即执行,以便我可以进一步编辑它。(所有这些都在源bash函数或脚本中,因此可以访问我的历史记录。)

我已经接近实现了,但还没有完全成功。

这会选择命令,但会立即运行:

eval $(history | "$HOME/bin/fzf" +s | sed 's/ *[0-9]* *//')

这将内容复制到我的剪贴板,但当我粘贴时,它仍然以空格和换行符结束,因此会立即执行。

history | "$HOME/bin/fzf" +s | sed 's/ *[0-9]* *//' | xclip -se c

我也尝试了几种变化,包括:
history | "$HOME/bin/fzf" +s | sed -e 's/ *[0-9]* *//' -e 's/$//' | xclip -se c

使用相同的结果。

这实际上是可行的,但我仍然需要将其放入剪贴板,然后手动粘贴。

history | "$HOME/bin/fzf" +s | sed -re 's/ *[0-9]* *//' | awk '{printf "%s", $0}' | xclip -se c

如何一步完成此操作,而不需要手动复制粘贴?

我认为只是省略xclip应该就可以完成,但这并不起作用。


你为什么不使用反向搜索(Ctrl和r)呢? - Raman Sailopal
1
我从来没有习惯使用那个。我只是尝试了一下。fzf更好用。它让我一次性看到很多选择,还有更多的搜索选项,不仅仅是一个接一个的。而且,我没有看到编辑我找到的东西的方式。当我按Enter键时,它只运行未修改的命令。此外,如果我能搞定这个,它可能会为自动获取命令行上的其他工作提供其他可能性。 - Joe
1
您可以多次按Ctrl-r键以浏览与输入文本相关的不同选项。然后,您可以按Esc键获取命令行上的命令进行编辑。我建议在尝试设计自己的选项之前先花时间研究已有的选项。 - Raman Sailopal
此外,如果您想在屏幕上显示与搜索相关的所有不同选项,您可以简单地使用历史记录并将其通过grep进行搜索。然后,您可以使用!<命令行号码>来执行该命令。 - Raman Sailopal
@RamanSailopal 这些是很好的建议。除了使用向上箭头返回之外,我并没有做过太多关于历史的事情。偶尔,我会尝试一个!后跟一些字符,但这很危险,因为它在你看到它是否选择了你想要的东西之前就运行了。不过,fzf似乎非常受欢迎,所以我不是唯一一个发现它有价值的人。此外,这些工具只需要几行代码来实现。我不是在编写自己的文本编辑器或mencoder的新版本。 - Joe
6个回答

2

fzf已经准备好在fzf的key-bindings.bash中安装此功能,由@sudavid4提到。 __fzf_history__函数使用fzf交互式地搜索bash历史记录。

在默认的历史处理中(虽然使用fzf的函数是不必要的),通过设置histverify启用选择后的编辑。来自man bash

histverify

如果设置,并且正在使用readline,则不会立即将历史替换的结果传递给shell解析器。相反,生成的行被加载到readline编辑缓冲区中,允许进一步修改。

最后,bash的内置命令fc(使用help而不是man了解更多信息)支持“从历史列表中显示或执行命令”,除了以“显示或操作历史记录列表”为重点的history内置命令。


还要注意...

fzf的key-bindings.bash代码片段:

  # CTRL-R - Paste the selected command from history into the command line
  bind -m emacs-standard -x '"\C-r": __fzf_history__'
  bind -m vi-command -x '"\C-r": __fzf_history__'
  bind -m vi-insert -x '"\C-r": __fzf_history__'

一个与之相关但目的不同的邻近bash shopt(shell选项):

histreedit

如果设置了并且正在使用readline,则用户有机会重新编辑失败的历史替换。


1

0
在当前的fzf版本中,ctrl-r的行为与您想要的完全相同。来自自述文件

CTRL-R - 将历史记录中选择的命令粘贴到命令行上

事实上,现在有些人希望 反过来

0
我想要通过fzf打开文件(而不是历史记录)的这种行为。
检查@mcint分享的链接:fzf's key-bind.bash 帮助我解决了我的用例:

CTRL-T:将所选文件路径粘贴到命令行中。

例如 vim CTRL-T

通过使用这种方法,带有扩展文件名的命令会出现在bash历史记录中。

0

在我看来,junegunn已经为您解决了这个问题。 在这个文件 中,他用您需要的功能替换了bash ctrl-r。由于fzf-file-widget输出sh:``fzf-file-widget':不是有效的标识符,我在源代码中遇到了一些小问题,但在将其更改为fzf_file_widget后,它运行得非常好。


你能否请示一个使用它的例子?我正在这样使用:alias scripts=ls ~/dotfiles/scripts | sed -e 's/\..*$//' | fzf-file-widget,但是出现了一个错误:“fzf-file-widget:zle:4: widgets can only be called when ZLE is active”。 - Guillermo kuster

0

我没有意识到这个问题从未得到完全回答。最终,我编写了一个函数,它位于$HOME/.bashrc中。

仍然需要按下粘贴键(Ctrl+Shift+v)才能在命令行上获得结果。

# fh - repeat history
fh () 
{ 
    history | tac | "$HOME/bin/fzf" +s | sed -re 's/ *[0-9]* *//' | awk '{printf "%s", $0}' | xclip -se c
}

它将选择的命令行复制到剪贴板中,以便您可以将其粘贴到命令行中进行进一步编辑和执行。

它将CLI历史记录通过管道发送到tac,反转顺序以使最近的命令首先显示出来(位于末尾),然后将其发送到fzf+s告诉fzf不要再次对输出进行排序。接下来,使用sed从结果中除去命令编号前缀。接着,经过awk处理,删除命令的尾随换行符,以便在粘贴时不会立即运行。最后,使用xclip将选择放入剪贴板。

最后,我添加了

bind '"\C-F":" fh\n"'  # fzf history on ctrl+F

添加到.bashrc以将该函数绑定到Ctrl+f,使其易于使用和记忆。

我在绑定的fh命令前加了一个前导空格,这样当它被调用时就不会添加到命令历史记录中。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接