我编写了一个函数来从 ssh 配置获取主机,而无需获取通配符主机:
sshConfAutoComplete() {
cat ~/.ssh/config | \
grep 'host ' | \
sed '
s#.*\*##g;
s#host ##g
'
}
输出:
pi
lynx
iridium
batchelorantor
rasp
输出是正确的,所以我将这个函数添加到:
/usr/local/etc/bash_completion.d/ssh
像这样:
sshConfAutoComplete() {
cat ~/.ssh/config | \
grep 'host ' | \
sed '
s#.*\*##g;
s#host ##g
'
}
complete -F sshConfAutoComplete ssh
然后我添加了这个来源. /usr/local/etc/bash_completion.d/ssh
:~/.bash_profile
Sourced ~/bash_profile
,然后当我输入ssh <tab>
以下内容时会出现:
pi
lynx
iridium
batchelorantor
rasp
如果我输入ssh ly <tab>
它不会自动完成 to lynx
,它只会输出上面的内容。
我该如何解决?
答案1
在man bash
标题为可编程完成解释了调用的函数如何-F
需要在数组变量中提供匹配结果COMPREPLY
。通常,命令提供的完整列表sed
会传递给命令,compgen -W
以便它尝试将单词与目标单词(即$2
函数的 arg 2 ( ))进行匹配。稍微简化一下我们得到:
sshConfAutoComplete() {
COMPREPLY=( $(compgen -W \
"$(sed -n ' /host /{s#.*\*##g; s#host ##g; p} ' ~/.ssh/config)" -- "$2"))
}
complete -F sshConfAutoComplete ssh
对于 MacOS,标准sed
命令不接受;
,因此每个命令必须换行:
COMPREPLY=( $(compgen -W \
"$(sed -n '/^host /{
s#.*\*##g
s#host ##g
p
}' ~/.ssh/config)" -- "$2"))
答案2
我做到了这一点并将其添加到我的~/bash_profile
:
IFS=$'\n'
getSshConfHosts() {
grep '^host' ~/.ssh/config | \
grep -v '[?*]' | \
cut -d ' ' -f 2-
}
sshConfAutoComplete() {
local cur prev opts
cur=${COMP_WORDS[COMP_CWORD]}
prev=${COMP_WORDS[COMP_CWORD-1]}
opts=$(getSshConfHosts)
COMPREPLY=( $(compgen -W "$opts" -- $cur ) )
}
complete -F sshConfAutoComplete ssh
我之前的 sed 命令在删除时留下了一个空行host *
更新
这个答案有效,但我把它给了接受的答案,因为他不知道我在 Mac 上,而且他也没有先写它。他的版本更容易理解。
我在另一个函数中使用正则表达式部分,所以我在我的bash_profile
:
IFS=$'\n'
getSshConfHosts() {
sed -n '/^host /{
s#.*\*##g
s#host ##g; p
}' ~/.ssh/config
}
sshConfAutoComplete() {
local wordList
wordList=$(getSshConfHosts)
COMPREPLY=( $(compgen -W "$wordList" -- $2 ) )
}
complete -F sshConfAutoComplete ssh