在 zsh 中循环空格分隔的字符串

Cha*_*rly 5 zsh

zsh中什么控制环境知道按空格分割?

我确信这很简单,但在我所有的搜索中尚未弄清楚是什么控制它。

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

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
Run Code Online (Sandbox Code Playgroud)

不同的方法通过shand工作bash,但在 shell 中,oh-my-zsh我无法按空格分隔,得到上面的结果。可能不是oh-my-zsh——但希望了解是什么推动了这一点。

bash 的工作示例:

s='foo bar baz'
for i in $s; do
  echo "$i END"
done
# foo END
# bar END
# baz END
Run Code Online (Sandbox Code Playgroud)

Gil*_*il' 6

Zsh 和 bash 是两种不同的编程语言。它们相似,但不完全相同。在 bash 中,更常见的是在 Bourne 风格的 shell 中(sh, dash,ksh, \xe2\x80\xa6) 中,不带引号的变量扩展$foo执行以下操作:

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

Zsh 基本上是一种 Bourne 风格的 shell,但它也有一些区别,这是主要的区别:$foo具有以下更简单的行为。

\n
    \n
  1. 获取变量 的值foo,它是一个字符串。(如果没有变量foo,则取空字符串。)
  2. \n
  3. 如果这导致空词,则该词被消除。(因此,例如$foo$bar,仅当 和 都被消除foobar均为空或未设置
  4. \n
\n

请注意,在 sh 或 bash 中,$foo仅当字符串不包含任何通配符或禁用通配符时才可分割字符串set -f

\n

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

\n
    \n
  • 使用= 指定的参数扩展来应用IFS分词。例如,$=foo在空白处进行分割,由下式确定IFS
  • \n
  • 使用p 参数扩展标志。例如${(p: :)foo}以空格分割(不是制表符或换行符)。
  • \n
\n

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

\n