在 zsh 中循环 space 分隔的字符串

Loop over space-separated string in zsh

在zsh中被space什么控制环境知道分了?

我确定它很简单,但在我所有的搜索中还没有弄清楚是什么控制了它。

尝试循环遍历 space 分隔字符串中的项目,如下所示:

s='foo bar baz'
for i in $s; do
  echo "$i END"
done
# foo bar baz END

# ---

s='foo bar baz'
a=( $s )
echo ${a[0]} # (empty)
echo ${a[1]} # foo bar baz

# ---

s='foo bar baz'
IFS=' ' read a <<< $s
for i in "${a[@]}"; do
  echo "$i END"
done
# foo bar baz END

不同的方法通过 shbash 起作用,但是在 shell 和 oh-my-zsh 中我无法通过 space 分开,得到以上结果。可能不是 oh-my-zsh - 但希望了解是什么推动了这一点。

来自 bash 的工作示例:

s='foo bar baz'
for i in $s; do
  echo "$i END"
done
# foo END
# bar END
# baz END

Zsh 和bash 是两种不同的编程语言。它们相似,但不完全相同。在 bash 中,更普遍的是在 Bourne 风格的 shell 中(shdashksh, …),一个不带引号的变量扩展 $foo执行以下操作:

  1. 取变量foo的值,是一个字符串。 (如果没有变量foo,取空字符串。)
  2. 将字符串拆分为以空格分隔的部分。 (更一般地说,IFS 变量的值决定了字符串的拆分方式;我不会在这里详述所有细节。)结果是一个字符串列表。
  3. 对于列表中的每个元素,如果它是一个通配符模式,即如果它包含至少一个通配符 *?\[(可能更多取决于某些 shell 选项),并且pattern 匹配至少一个文件名,然后该元素被匹配文件名列表替换。不包含任何通配符的元素,以及包含通配符但不匹配任何文件名的元素将被保留。结果又是一个字符串列表。

Zsh 主要是 Bourne 风格 shell,但它有一些差异,这是主要的差异:$foo 具有以下更简单的行为。

  1. 取变量foo的值,是一个字符串。 (如果没有变量foo,取空字符串。)
  2. 如果这导致一个空词,这个词被淘汰。 (因此,例如 $foo$bar 仅在 foobar 均为空或未设置时才被消除。)

请注意,在 sh 或 bash 中,$foo 仅在字符串不包含任何通配符或使用 set -f 禁用 globbing 时才用于拆分字符串。

在 zsh 中,要在空格处拆分字符串,有两种简单的方法:

这与 oh-my-zsh 无关,oh-my-zsh 是一个配置 zsh 以供交互使用的插件。