zsh:将命令映射到数组

zsh:将命令映射到数组

假设你有一个数组a=(foo 'bar baz')

有没有比这更明显的方法将命令/函数应用于每个数组元素并将结果字符串保存到另一个数组中:

b=()
for e in $a; do
    b+=("$(my_cmd "$e")")
done

答案1

您始终可以为此声明一个函数:

map() {
  local arrayname="$1" cmd="$2" i
  shift 2
  eval "$arrayname=()"
  for i do
    eval "$arrayname+=(\"\$($cmd)\")"
  done
}

并用作:

$ a=(a '' bcd)
$ map b 'wc -c <<< "$i"' "$a[@]"
$ echo $b
2 1 4

答案2

如果您事先知道该命令对数组元素执行的操作,那么您可以使用参数扩展标志(请参阅man zshexpn)指导zsh如何将命令输出调整为数组。


例子

假设一个数组a包含文件名,每个文件仅包含一行文本:

$ a=(foo 'bar baz')
$ cat foo
A
$ cat 'bar baz'
B C

现在为了论证起见,我们假设该命令只是将文件的内容cat放入数组中。b在这种情况下,我们可以简单地写而不是循环

b=(${(f)"$(cat "${a[@]}")"})

where(f)将 的结果分割cat成换行符处的分隔词。

结果如预期:

$ echo "${b[1]}"
A
$ echo "${b[2]}"
B C

根据实际情况,您可以使用 flag 拆分不同的字符ps:<character>:。其中一些如上(ps:\n:)例中的换行符或 NULL 字符分别(ps:\0:)具有简写:(f)(0)

答案3

你可以这样做:

eval "b=(" '"$(cmd "$a['{1..$#a}']")"' ")"

但这不太清晰。

答案4

只是注意一下:

你可以用以下方法缩短它:

for e ($a) b+=("$(my_cmd "$e")")

请注意,$a循环遍历非空元素。要循环所有元素,它是"$a[@]".

相关内容