![如何创建一个重新配置 shell 配置的键绑定,而不将新命令保存在历史记录中?](https://linux22.com/image/113241/%E5%A6%82%E4%BD%95%E5%88%9B%E5%BB%BA%E4%B8%80%E4%B8%AA%E9%87%8D%E6%96%B0%E9%85%8D%E7%BD%AE%20shell%20%E9%85%8D%E7%BD%AE%E7%9A%84%E9%94%AE%E7%BB%91%E5%AE%9A%EF%BC%8C%E8%80%8C%E4%B8%8D%E5%B0%86%E6%96%B0%E5%91%BD%E4%BB%A4%E4%BF%9D%E5%AD%98%E5%9C%A8%E5%8E%86%E5%8F%B2%E8%AE%B0%E5%BD%95%E4%B8%AD%EF%BC%9F.png)
我想使用键序列创建一个键绑定,以重新加载存储在 中C-x r
的配置以及存储在 中的 readline 库之一。bash
~/.bashrc
~/.inputrc
要重新加载 readline 的配置,我想我可以使用re-read-init-file
以下中描述的函数man 3 readline
:
re-read-init-file (C-x C-r)
Read in the contents of the inputrc file, and incorporate any bindings or variable assignments found there.
要重新加载 的配置bash
,我可以使用source
or.
命令。但是,我不确定将 shell 命令与 readline 函数结合起来的最佳方法是什么。因此,我想出了 2 个键绑定的组合:
bind '"\C-xr": ". ~/.bashrc \C-x\C-z1\C-m"'
bind '"\C-x\C-z1": re-read-init-file'
当我点击C-x r
bash 时,会发生以下情况:
. ~/.bashrc `~/.bashrc` is inserted on the command line
C-x C-z 1 `C-x C-z 1` is typed which is bound to `re-read-init-file`
C-m `C-m` is hit which executes the current command line
它似乎有效,因为在 tmux 内部,如果我有 2 个窗格,一个用于编辑~/.inputrc
或~/.bashrc
,另一个用于 shell,并且我更改配置文件,在敲入C-x r
shell 后,我可以看到更改生效(无论是新别名或新键绑定),无需关闭窗格即可重新打开新 shell。
但是,有没有更好的方法来达到相同的结果呢?特别是,是否可以执行命令而不在历史记录中留下条目?因为如果我点击C-p
回忆最后执行的命令,我会得到. ~/.bashrc
,而我更愿意直接获取在重新获取 shell 配置之前执行的命令。
我有同样的问题zsh
:
bindkey -s '^Xr' '. ~/.zshrc^M'
同样,点击 后C-x r
,该命令. ~/.zshrc
将记录在历史记录中。有没有更好的方法来重新配置 的源zsh
?
答案1
不要将命令插入命令行来运行它!这是非常脆弱的——你正在尝试的假设是在当前提示符下还没有输入任何内容。相反,请将密钥绑定到 shell 命令,而不是将其绑定到行编辑命令。
在 bash 中,使用bind -x
。
bind -x '"\C-xr": . ~/.bashrc'
如果您还想重新读取 readline 配置,则没有一种简单的方法可以在键绑定中混合 readline 命令和 bash 命令。一种笨拙的方法是将键绑定到包含两个键序列的 readline 宏,一个绑定到要执行的 readline 命令,一个绑定到 bash 命令。
bind '"\e[99i~": re-read-init-file'
bind -x '"\e[99b~": . ~/.bashrc'
bind '"\C-xr": "\e[99i~\e[99b~"'
在 zsh 中,使用zle -N
将函数声明为小部件,然后bindkey
将该小部件绑定到一个键。
reread_zshrc () {
. ~/.zshrc
}
zle -N reread_zshrc
bindkey '^Xr' reread_zshrc
答案2
在 中man bash
,我找到了HISTIGNORE
环境变量,其描述如下:
HISTIGNORE
A colon-separated list of patterns used to decide which command
lines should be saved on the history list. Each pattern is anchored
at the beginning of the line and must match the complete line (no
implicit `*' is appended). Each pattern is tested against the line
after the checks specified by HISTCONTROL are applied. In addition
to the normal shell pattern matching characters, `&' matches the
previous history line. `&' may be escaped using a backslash; the
backslash is removed before attempting a match. The second and
subsequent lines of a multi-line compound command are not tested,
and are added to the history regardless of the value of HISTIGNORE.
因此,我在 中导出了以下值~/.bashrc
:
bind '"\C-xr": ". ~/.bashrc \C-x\C-z1\C-m"'
bind '"\C-x\C-z1": re-read-init-file'
export HISTIGNORE="clear:history:. ~/.bashrc "
最后一行应该防止bash
保存任何命令clear
,history
更重要的是 . ~/.bashrc
命令。
对于zsh
,我找到了该HIST_IGNORE_SPACE
选项,其描述如下man zshoptions
:
HIST_IGNORE_SPACE (-g)
Remove command lines from the history list when the first character on
the line is a space, or when one of the expanded aliases contains a
leading space. Only normal aliases (not global or suffix aliases) have
this behaviour. Note that the command lingers in the internal history
until the next command is entered before it vanishes, allowing you to
briefly reuse or edit the line. If you want to make it vanish right away
without entering another command, type a space and press return.
根据它的说法,如果启用此选项,zsh
应从历史记录中删除任何以空格开头的命令。但是,它会暂时保留在内部历史记录中,直到执行下一个命令。因此,我在 中设置了此选项~/.zshrc
,然后重新定义了键绑定以重新配置 shell 的配置,如下所示:
setopt HIST_IGNORE_SPACE
bindkey -s '^Xr' ' . ~/.zshrc^M ^M'
# │ │
# │ └─ command containing only a space to force `zsh`
# │ to “forget“ the previous command immediately
# └─ space added to prevent `zsh` from logging the command