bash readline:执行外部命令的键绑定

bash readline:执行外部命令的键绑定

(背景:我是 tcsh 的长期用户,逐渐过渡到 bash,并试图找到一些有用的 tcsh 特定功能的等效项。)

在 tcsh 中,我可以定义执行外部命令的键绑定。例如,给定:

bindkey -c ^Gu uptime

我可以在 tcsh 中输入“Control-G u”,它将执行该uptime命令。我不必输入 Enter,该命令不会出现在我的历史记录中,而且我可以在输入行的中间执行此操作(我发现后者对于某些命令特别有用)。

bash 通过 GNU readline 库具有类似的键绑定机制,并在$HOME/.inputrc(或其他地方)中指定了绑定。但在阅读info readline文档后,我没有看到按键绑定执行外部命令的方法。

我想到的最接近的事情是将这样的内容添加到我的.inputrc文件中:

"\C-gu": "uptime\n"

但这并不执行命令;相反,它的行为就好像我先输入了内容,uptime然后按 Enter 键。该命令出现在我的历史记录中(没关系),并且它仅适用于空行;如果我输入"echo control-Gu",那么它会打印uptime而不是执行命令。

另一个小缺点是绑定会影响使用 GNU readline 的其他命令,例如 Perl 调试器。

有没有办法bindkey -c通过将按键序列映射到指定外部命令的执行来模拟 bash 中 tcsh 的效果?

如果重要的话,我在 Ubuntu 12.04 beta 2 上使用 bash 4.2.24。

答案1

并非所有行编辑都由;bash控制。~/.inputrc其中大部分是通过bind内置配置的。在这种情况下,你想要类似的东西

bind -x '"\C-gu":uptime'

在你的~/.bashrc

答案2

另一个答案提供了一个解决方案,在新行中执行命令。这在某些情况下很有用,但大多数时候我的工作流程是这样的,要么我想要

  • 将内联执行命令的结果插入我的当前的命令行(下面的示例)
  • 真正在后台执行命令,无输出,当前命令行不发生变化

我比 @geekosaur 所展示的变体更频繁地使用这两个原则。这是一个例子:

bind '"\C-gd":"\C-u`date +%Y%m%d%H%M`\e\C-e\C-a\C-y\C-e"'

此绑定CTRL-gd终止现有命令(将其保存在剪切缓冲区中),插入some shell command(在本例中date +%Y%m%d%H%M是为了获得良好的时间戳),就地执行该命令,然后将保存的命令粘贴回命令行的前面。

我有一堆命令,它们从我的系统输出一些信息,我经常在其他命令行中使用它们,思考get_lan_ip, get_gw_ip, get_gw_pubip, get_ns_ip, get_root_block_dev, get_email_addr, get_phone_number等等。基本上就像可编程缩写!所有这些都\C-g只需按一下键即可完成。

对我来说另一个非常有用的用例是内联调用函数,即不要产生输出,但默默地触发后台操作,就像mediaplayer_next, mediaplayer_pause, speakerphone_answer, ...当我想在不离开终端的情况下触发某些事情时,并且不会暂时忽略当前的窗口内容;)

答案3

要添加已接受的答案,您实际上不需要使用bind -x.您仍然可以将其添加到您的inputrc,但不是\n在序列的末尾,它必须是 的绑定accept-line。例如:

"\C-m": accept-line
"\C-gu": "uptime\C-m"

由于它会导致uptime输入命令行,因此它将记录在您的历史记录中,这可能是优点也可能是缺点,具体取决于您的用例。

^M是 Mac 和 Windows 上的回车符,但顺序是什么并不重要。例如,以下内容也适用:

"\xxacceptline": accept-line
"\C-gu": "uptime\xxacceptline"

答案4

要添加一些技巧,你可以用接受的答案来做,你甚至可以使用类似

bind -x '"\C-g": echo -en "\e[6t"'

将当前窗口发送到底部,或 xterm 发明的其他转义代码以使窗口居中、将窗口放置在特定像素位置等。

另请参阅vttest(1)(事实证明,您可以通过玩弄来学习很多奇特的转义序列vttest)和https://invisible-island.net/xterm/ctlseqs/ctlseqs.html

相关内容