(背景:我是 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