通过换行符从 subshel​​l 拆分 zsh 数组

pse*_*ert 5 zsh array shell-script

我想从子外壳实例化 zsh 数组

myarray=($(somecommand)
Run Code Online (Sandbox Code Playgroud)

我检查我是否收到了我想要的东西

for element in $myarray ; do echo "===" ; echo $element ; echo "---" ; done
Run Code Online (Sandbox Code Playgroud)

默认情况下,我看到空格(空格和换行符)用于分隔元素。

我还发现我可以使用${(s:-:)"$(somecommand)"}分隔 by -,在这种情况下,空格和换行符不会破坏元素(即数组元素可以包含换行符)。

到目前为止,我仅在换行符处无法拆分。即如果somecommand返回

Alice
Bob
Arthur C Clarke
Neo
Thomas Anderson
Run Code Online (Sandbox Code Playgroud)

我希望我上面的for循环打印:

===
Alice
---
===
Bob
---
===
Arthur C Clarke
---
===
Neo
---
===
Thomas Anderson
---
Run Code Online (Sandbox Code Playgroud)

我如何做到这一点?(并且可能会指示在手册中查找的位置。)

Sté*_*las 13

本机拆分运算符(除了$IFS在不带引号的命令替换上完成的类似 Bourne 的分词之外)带有s参数扩展标志:

array=(${(ps:\n:)"$(cmd)"})
Run Code Online (Sandbox Code Playgroud)

cmd在换行符上拆分输出,丢弃空元素(空行)。

p是启用这些\x扩展。由于ps:\n:是常见的一种,它有一个较短的别名:f(上线分离˚F电火工品):

array=(${(f)"$(cmd)"})
Run Code Online (Sandbox Code Playgroud)

要保留空行,您可以执行以下操作:

array=("${(f@)$(cmd)"})
Run Code Online (Sandbox Code Playgroud)

现在,请注意,与大多数其他 shell 一样,命令替换会删除所有尾随换行符,因此所有尾随空行。要保留这些,您可以执行以下操作:

array=("${(f@)$(cmd; echo .)}")
array[-1]=()  # remove that last line added by echo .
Run Code Online (Sandbox Code Playgroud)

随着$IFS词的拆分:

IFS=$'\n'
array=($(cmd)) # removes empty lines. Note that contrary to other
               # Bourne-like shells, zsh doesn't do globbing there
               # so you don't need the "set -o noglob"

IFS=$'\n\n' # like in ksh93, doubling an IFS-whitespace character
            # removes its special treatment as a whitespace character
array=($(cmd)) # preserves empty lines except the trailing ones

IFS=$'\n\n'
array=($(cmd; echo .)); array[-1]=() # preserves all empty lines.
Run Code Online (Sandbox Code Playgroud)

为了避免$IFS全局修改,您可以在匿名函数中执行上述操作:

(){
  local IFS=$'\n\n'
  array=($(cmd; echo .)); array[-1]=()
}
Run Code Online (Sandbox Code Playgroud)

还要注意$array扩展会跳过空元素。因此,如果您想遍历包括空元素在内的所有元素,则需要:

for i ("$array[@]") ...
Run Code Online (Sandbox Code Playgroud)

或者

for i ("${(@)array}") ...
Run Code Online (Sandbox Code Playgroud)

不是

for i ($array) ...
for i in $array
Run Code Online (Sandbox Code Playgroud)