为什么zsh中IFS需要echo才能生效?

Jon*_*n H 0 zsh array echo

我正在尝试PATH使用 zsh 5.8 将 的成员读入数组。我习惯使用 Bash,通常可以执行以下操作:

IFS=: p=($PATH)
Run Code Online (Sandbox Code Playgroud)

然而,对于 zsh,这实际上给了我一个只有一项的数组。如果我改写:

IFS=: p=($(echo $PATH))
Run Code Online (Sandbox Code Playgroud)

然后我得到正确的元素数量。这是为什么?

ilk*_*chu 5

因为 zsh 默认情况下不会对参数扩展进行分词,这与 POSIXy shell 不同。它适用于命令替换,因此通过一个往返可以为您“修复”它。但在 zsh 中这仍然远不是正确的做法,并且echo命令替换的组合在某些情况下甚至可能会破坏数据。

在 zsh 中,您可以$=PATH要求进行分词,或者使用此处提供的更合适的解决方案:How to split a string by ':' character in bash/zsh?

另外,在 的情况下PATH,默认情况下它与 zsh 中的数组变量绑定path,因此您无需执行任何操作即可将其作为数组访问。


(在 中IFS=: p=($PATH),不带引号的扩展也会受到文件名生成或通配符的影响,因此,如果 中的任何路径PATH碰巧包含通配符(*?[],也许是其他字符),结果可能不是您想要的。通过命令替换进行往返并且echo还会删除任何尾随的换行符,并且(取决于echo)也可能会破坏反斜杠。)

  • @JonathanH,嗯。Zsh 可能有点...难以阅读所有单字符修饰符。但 `parts=(${(s/:/)str})` 仍然很清楚。在数组赋值中,我们有 `${(s/:/)str}`,它只是像 `${str}` 或 `$str` 一样的参数扩展,但带有 `s/:/` 修饰符来告诉它在 `:` 上分割(我想 `s` 表示分割,而 `/` 只是分隔符,用括号将其标记为修饰符)。在需要的地方提供分隔符会更干净,因为对“IFS”的更改也可能影响脚本的其余部分。 (2认同)