通过换行符从子 shell 中分割 zsh 数组

通过换行符从子 shell 中分割 zsh 数组

我想从子 shell 实例化一个 zsh 数组

myarray=($(somecommand)

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

for element in $myarray ; do echo "===" ; echo $element ; echo "---" ; done

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

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

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

Alice
Bob
Arthur C Clarke
Neo
Thomas Anderson

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

===
Alice
---
===
Bob
---
===
Arthur C Clarke
---
===
Neo
---
===
Thomas Anderson
---

我该如何实现这一目标? (可能还指出在手册中查找该内容的位置。)

答案1

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

array=(${(ps:\n:)"$(cmd)"})

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

p是为了启用这些\x扩展。与ps:\n:常见的一样,它有一个更短的别名:(f在线拆分F种子):

array=(${(f)"$(cmd)"})

要保留空行,您可以这样做:

array=("${(f@)$(cmd)"})

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

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

通过$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.

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

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

另请注意,$array扩展会跳过空元素。所以如果你想循环全部包括空元素在内的元素,您需要:

for i ("$array[@]") ...

或者

for i ("${(@)array}") ...

不是

for i ($array) ...
for i in $array

相关内容