![bash 中 emacs 风格的键绑定的令人困惑的行为](https://linux22.com/image/54204/bash%20%E4%B8%AD%20emacs%20%E9%A3%8E%E6%A0%BC%E7%9A%84%E9%94%AE%E7%BB%91%E5%AE%9A%E7%9A%84%E4%BB%A4%E4%BA%BA%E5%9B%B0%E6%83%91%E7%9A%84%E8%A1%8C%E4%B8%BA.png)
Bash 提供了许多有用的emacs-style keybindings
简单命令行编辑功能。例如,Ctrl+w删除(“杀死”)光标左侧的单词。
另一个键绑定Alt+d应该是第一个键绑定的“镜像”。它应该从光标处删除一个单词。
然而,我注意到,这两个键绑定的行为并不完全对称。而Ctrl+w视为foo.bar
一个词,Alt+d将其视为两个词
更烦人的# echo
是,是两个词Ctrl+w,却是一个词Alt+d。
这其中有什么逻辑吗?他们不以同样的方式对待文字有什么原因吗?
我有什么办法可以改变这个吗?
我正在使用 bashDebian Wheezy
答案1
不同的 bash 命令使用不同的单词概念。查看命令中各个命令的说明手动的。
C-w
杀死前一个空白。M-DEL
(通常Alt+ ) 杀死到前一个单词边界,其中单词仅包含字母和数字(与和BackSpace相同),并类似地向前杀死。M-b
M-f
M-d
Bash 使用 Readline 库来处理用户输入,并且可以通过以下方式进行配置~/.inputrc
或通过bind
内置于~/.bashrc
.您可以将一个密钥绑定到不同的密钥读行命令如果你希望。您还可以使用bind -x
将键绑定到修改READLINE_LINE
变量的 bash 函数。
例如,要使M-d
Kill 成为 shell 单词,请将其绑定到shell-kill-word
在你的.bashrc
:
bind '"\M-d": shell-kill-word'
要M-d
删除以空格分隔的单词,没有内置函数,因此您需要编写宏或 shell 函数。由于没有由空格分隔的单词进行的运动命令,因此至少该部分需要一个函数。
delete_whitespace_word () {
local suffix="${READLINE_LINE:$READLINE_POINT}"
if [[ $suffix =~ ^[[:space:]]*[^[:space:]]+ ]]; then
local -i s=READLINE_POINT+${#BASH_REMATCH[0]}
READLINE_LINE="${READLINE_LINE:0:$READLINE_POINT}${READLINE_LINE:$s}"
fi
}
bind -x '"\ed": delete_whitespace_word'
让M-d
kill成为一个以空格分隔的单词更复杂,因为据我所知,没有办法从bash代码访问kill环。因此,这需要一个函数来查找要杀死的部分的末尾,以及一个宏来跟随实际的杀死。
forward_whitespace_word () {
local suffix="${READLINE_LINE:$READLINE_POINT}"
if [[ $suffix =~ ^[[:space:]]*[^[:space:]]+ ]]; then
((READLINE_POINT += ${#BASH_REMATCH[0]}))
else
READLINE_POINT=${#READLINE_LINE}
fi
}
bind -x '"\C-xF": forward_whitespace_word'
bind '"\C-x\C-w": kill-region'
bind '"\ed": "\e \C-xF\C-x\C-w"'
所有这一切在 zsh 中都会容易得多。
答案2
Readline 已经有vi-fword
和 ,vi-bword
它使用空格作为单词边界,因此不需要 Gilles 的forward_whitespace_word
函数。
vi-fword
后跟unix-word-rubout
( \C-w
) 向后删除以空格分隔的单词(包括尾随空格)。
bind '"\eb":vi-bword'
bind '"\ef":vi-fword'
bind '"\ed":"\ef\C-w"'
vi-backward-word
是 的别名vi-bword
,vi-forward-word
是 的别名vi-fword
,vi-backward-bigword
是 的别名vi-bWord
,vi-forward-bigword
是 的别名vi-fWord
。
答案3
这是方法的结果阅读线对待“词”。Altd是以下的快捷方式kill-word
:
从当前单词的末尾处终止,或者如果在单词之间,则终止到下一个单词的末尾。字边界与 Mf 使用的相同(前向词)。
中的单词边界forward-word
定义如下:
单词由字母和数字组成。
而Ctrlw是 的快捷方式unix-word-rubout
:
杀掉点后面的字,使用空格作为单词边界。
因此,要使用 的示例foo.bar
,第一个命令将字符串视为由 分隔的两个“单词” .
,而第二个命令看不到空格,因此将其视为单个“单词”。