Bash补全在ZSH/Oh-My-ZSH失效:COMP_WORDS非数组问题咨询
解决方案
有两种可行方案,优先推荐修改补全脚本实现跨Shell兼容,无需用户修改本地ZSH配置。
方案1:修改补全脚本(推荐)
只需要在原有补全函数开头加入ZSH适配逻辑即可同时兼容Bash和ZSH,修改后完整脚本如下:
#!/usr/bin/env bash # This bash completions script was generated by # completely (https://github.com/dannyben/completely) # Modifying it manually is not recommended _cli_completions() { # ========== 新增ZSH适配逻辑 Start ========== if [[ -n "$ZSH_VERSION" ]]; then # 将COMP_LINE拆分为数组对齐Bash的COMP_WORDS行为 typeset -ga COMP_WORDS COMP_WORDS=("${(z)COMP_LINE}") # 对齐Bash的0基索引 (( COMP_CWORD-- )) fi # ========== 新增ZSH适配逻辑 End ========== local cur=${COMP_WORDS[COMP_CWORD]} # 把*改成@,数组切片行为在两类Shell下更统一 local comp_line="${COMP_WORDS[@]:1}" case "$comp_line" in 'completions'*) COMPREPLY=($(compgen -W "--help -h" -- "$cur")) ;; 'download'*) COMPREPLY=($(compgen -W "--force --help -f -h" -- "$cur")) ;; ''*) COMPREPLY=($(compgen -W "--help --version -h -v completions download" -- "$cur")) ;; esac } # ZSH环境下自动加载Bash补全兼容模块 if [[ -n "$ZSH_VERSION" && ! $(whence complete) ]]; then autoload -U bashcompinit bashcompinit fi complete -F _cli_completions cli
修改说明:
- ZSH内置的
${(z)}参数扩展可以将命令行字符串拆分为和Bash行为一致的单词数组,直接对齐COMP_WORDS的结构 - 自动判断ZSH环境下是否存在
complete命令,不存在则自动加载bashcompinit兼容模块,无需用户手动配置 - 数组切片写法优化,避免两类Shell的语法差异问题
方案2:修改本地ZSH配置
如果不想修改补全脚本,可以在本地.zshrc的compinit配置后新增一行加载Bash补全兼容模块的配置:
fpath=($ZSH/functions $ZSH/completions $fpath) autoload -U compaudit compinit # 新增以下行 autoload -U bashcompinit && bashcompinit
修改后执行source ~/.zshrc生效即可。这种方案的缺点是所有使用该工具的ZSH用户都需要手动修改配置,通用性较差。
额外说明
你之前尝试的setopt shwordsplit无效是因为该参数仅控制字符串拆分规则,不会自动将ZSH下默认是字符串类型的COMP_WORDS转为数组,无法解决根源问题。
内容的提问来源于stack exchange,提问作者Nicolas
相关产品推荐
相关产品推荐

