【问题标题】:How do I populate a bash array with multi-line command output?如何使用多行命令输出填充 bash 数组?
【发布时间】:2016-09-17 00:45:09
【问题描述】:

如何使用多行命令输出填充 bash 数组?

例如给出这个 printf 命令:

$ printf 'a\nb\n\nc\n\nd\ne\nf\n\n'
a
b

c

d
e
f

我想填充一个 bash 数组,就像我写的一样:

$ arr[0]='a
b'
$ arr[1]='c'
$ arr[2]='d
e
f'

所以可以循环遍历它:

$ for i in "${arr[@]}"; do printf "<%s>\n" "$i"; done
<a
b>
<c>
<d
e
f>

我尝试了各种使用 NUL 字符来分隔我想要的数组字段而不是空行的化身,因为这似乎是我最好的选择,但到目前为止还没有运气,例如:

$ IFS=$'\0' declare -a arr="( $(printf 'a\nb\n\0c\n\0d\ne\nf\n\0') )"
$ for i in "${arr[@]}"; do printf "<%s>\n" "$i"; done
<a>
<b>
<c>
<d>
<e>
<f>

我也试过mapfile -d $'\0',但我的地图文件不支持-d

我确实发现这行得通:

$ declare -a arr="( $(printf '"a\nb" "c" "d\ne\nf"') )"
$ for i in "${arr[@]}"; do printf "<%s>\n" "$i"; done
<a
b>
<c>
<d
e
f>

但这似乎有点笨拙,当我真正希望它告诉 shell 使用除空白以外的某些字符作为数组字段分隔符时,我不得不转义 "s。

【问题讨论】:

  • 仅供参考,mapfile in bash 4.4 支持 -d 并于今天发布。

标签: bash


【解决方案1】:

最佳实践方法,使用 NUL 分隔符:

arr=( )
while IFS= read -r -d '' item; do
  arr+=( "$item" )
done < <(printf 'a\nb\n\0c\n\0d\ne\nf\n\0')

...使用 bash 4.4 会更简单:

mapfile -t -d '' arr < <(printf 'a\nb\n\0c\n\0d\ne\nf\n\0')

更粗略的说,支持双换行符的方法:

item=''
array=( )
while IFS= read -r line; do
  if [[ $line ]]; then
    if [[ $item ]]; then
      item+=$'\n'"$line"
    else
      item="$line"
    fi
  else
    [[ $item ]] && {
      array+=( "$item" )
      item=''
    }
  fi
done < <(printf 'a\nb\n\nc\n\nd\ne\nf\n\n')

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-23
    • 1970-01-01
    • 1970-01-01
    • 2011-07-27
    • 2012-02-04
    • 1970-01-01
    相关资源
    最近更新 更多