这两种 zsh 补全方法有什么不同?

What is different about these two zsh completion methods?

我已经创建了一个 zsh 完成脚本。如果我对选项列表进行硬编码,它会按预期工作,但如果我尝试使用 bash 命令生成相同的硬编码值,我的结果将出乎意料。出于这个问题的目的,我将这两种方法组合到同一个完成脚本中。 "silly" 很奇怪。 "silly2" 表现符合预期。

#compdef silly

_silly() {
    local -a options
    options=($(cat in_file.txt))
    _describe 'silly command' options && ret=0
    return ret
}

_silly2() {
    local -a options
    options=("one:Does the 1 thing" "two:Does the 2 thing")
    _describe 'silly2 command' options && ret=0
    return ret
}

compdef _silly silly
compdef _silly2 silly2

#contents of in_file.txt
#"one:Does the 1 thing" "two:Does the 2 thing"

如您所见,第二种方法(硬编码)采用输入字符串 "one:Does...",而第一种方法(动态)通过对文件 in_file.txt 的 cat 调用生成完全相同的输出,具有相同的文本。

理想情况下,结果如下所示:

one  -- Does the 1 thing
two  -- Does the 2 thing

第二个确实产生了这个结果。然而,第一个产生的结果如下:

"two  "one  -- Does
1                          2             the            thing"

我一辈子都弄不明白这里有什么区别!

我在这里回答我自己的问题。答案来自一个相关问题:How to pass the contents of a file using `cat` to `_values` (zsh completion)

基本上,如果空格来自 bash 命令的结果而不是字符串文字,它们将被区别对待。解决方案是在命令执行期间更改 bash 内部字段分隔符,然后再改回来。

OLD_IFS=$IFS
IFS=$'\n'
options=($(cat in_file.txt))
_describe 'silly command' options && ret=0
IFS=$OLD_IFS

这使得两个命令的行为相同。