![在 bash 中使用 compgen 获得不区分大小写的补全](https://linux22.com/image/65511/%E5%9C%A8%20bash%20%E4%B8%AD%E4%BD%BF%E7%94%A8%20compgen%20%E8%8E%B7%E5%BE%97%E4%B8%8D%E5%8C%BA%E5%88%86%E5%A4%A7%E5%B0%8F%E5%86%99%E7%9A%84%E8%A1%A5%E5%85%A8.png)
我正在尝试使用 bash 自动完成我的命令(devmode2)复合基因-W,我的 bashrc 有:
_devmode2() {
COMPREPLY=()
local sonames=$(devmode2 --auto --current "${COMP_CWORD}" -- ${COMP_WORDS[@]})
COMPREPLY=($(compgen -W "${sonames}" -- ${COMP_WORDS[COMP_CWORD]}))
}
complete -F _devmode2 devmode2
自动完成示例
$ devmode2 g<tab>
结果是索纳梅斯具有以下值:
game-life-adv
game-life-sparse
getopt-alt
git-workflow
git-workflow-extra
github-testers
group-git
group-git-ivan
Group-Git-Taggers-Maven
Group-Git-Taggers-Node
Group-Git-Taggers-Perl
Group-Git-Taggers-Ruby
但我的自动完成会产生以下建议:
game-life-adv game-life-sparse getopt-alt github-testers git-workflow git-workflow-extra group-git group-git-ivan
我怎样才能获得我传递给的所有值康普根后退?
答案1
据我所知,compgen
没有选项可以对您提供的选项列表进行不区分大小写的过滤。
您可以设置一个readline
变量以使文件名完成不区分大小写:
bind "set completion-ignore-case on"
但这不会影响 的行为compgen
,因此它可能不适用于可编程完成。 (它的行为对于文件名也有点奇怪。)
这使您可以进行自己的过滤,而不是使用compgen
(或者如果您需要过滤以外的功能,则与 结合使用compgen
,这在您的示例中不是这种情况)。
您可以通过对替代列表进行简单迭代,进行不区分大小写的前缀比较来做到这一点,但以下小函数应该可以工作:
_devmode2() {
local sonames=($(devmode2 --auto --current "${COMP_CWORD}" -- ${COMP_WORDS[@]}))
local prefix="${COMP_WORDS[COMP_CWORD]}"
COMPREPLY=($(printf %s\\n "${sonames[@]}" |
awk -v IGNORECASE=1 -v p="$prefix" \
'p==substr($0,0,length(p))'))
}
如果devmode2
每行输出一个替代方案,则将其用作 的输入会更容易awk
。另外,据我所知,完成函数的第二个参数始终与 相同${COMP_WORDS[COMP_CWORD]}
。所以这可能更简单:
_devmode2() {
COMPREPLY=($(devmode2 -auto --current "${COMP_CWORD}" -- "${COMP_WORDS[@]}" \
awk -v IGNORECASE=1 -v p="$2" \
'p==substr($0,0,length(p))'))
}