BASH数组变量名称连接

时间:2016-03-11 20:15:47

标签: arrays bash concatenation

我在BASH中使用变量名称连接或替换时遇到了一些问题。鉴于:

#!/bin/bash
Audio1=(0:ita, 96k, AAC, 2.0, s16le, 48000)   # audio stream definitions
Audio2=(1:rus, 128k, AAC, 2.0, s16le, 48000)  # for use in ffmpeg or
Audio3=(2:klg, 96k, AAC, 1.0, s16le, 48000)   # avconv
# and so on, now processing the audio streams
for ((i=1 ; i<=8 ; i++)) ; do
  Audio="Audio$i"
  Audio=${!Audio}
  if [ ${#Audio[0]} -gt 0 ] ; then
    # do the job with $Audio, here examplaryly:
    echo ${Audio[@]}
  fi
done

预期结果是:

0:ita, 96k, AAC, 2.0, s16le, 48000
1:rus, 128k, AAC, 2.0, s16le, 48000
2:klg, 96k, AAC, 1.0, s16le, 48000

我得到了:

0:ita,
1:rus,
2:klg,

这只是解决方案的一半,因为每个源数组只复制了第一个元素,而不是完全复制到工作数组$ Audio中。在PHP中,我会简单地通过以下方式编写变量名称替换:

for ($i=1; $i<=8; $i++) {
  $Audio = ${'Audio'.$i};     // ← that’s all the magic in PHP ;-)
  if (isset($Audio[0])) {
    // blabla
  }
}

不幸的是,我不能将PHP用于此应用程序。当然,这是我在BASH的第一个脚本之一。切换到任何其他编码(例如,许多简单变量而不是少数阵列)不是一种选择。我必须使用这些预设。那么,我的错在哪里,出了什么问题?

问候 - 伯特

2 个答案:

答案 0 :(得分:1)

在BASH版本4.3+中,您可以使用declare -n

for ((i=1 ; i<=3; i++)) ; do
   declare -n Audio="Audio$i"
   if [[ ${#Audio[@]} -gt 0 ]]; then
       echo "${Audio[@]}"
   fi
done

0:ita, 96k, AAC, 2.0, s16le, 48000
1:rus, 128k, AAC, 2.0, s16le, 48000
2:klg, 96k, AAC, 1.0, s16le, 48000

-n使NAME成为对其value命名的变量的引用。因此,在上面的代码Audio中引用了Audio1Audio2Audio3等中包含的值。

答案 1 :(得分:1)

不使用namerefs,你可以这样做:

Audio1=(0:ita, 96k, AAC, 2.0, s16le, 48000)   # audio stream definitions
Audio2=(1:rus, 128k, AAC, 2.0, s16le, 48000)  # for use in ffmpeg or
Audio3=(2:klg, 96k, AAC, 1.0, s16le, 48000)   # avconv

for i in {1..3}; do
    aryvar="Audio${i}[@]"   # this is the special magic indirect varname
    for value in "${!aryvar}"; do printf "%d\t%s\n" $i "$value"; done
    # ...........^^^^^^^^^^^^ expands to elements of the array
done

输出

1   0:ita,
1   96k,
1   AAC,
1   2.0,
1   s16le,
1   48000
2   1:rus,
2   128k,
2   AAC,
2   2.0,
2   s16le,
2   48000
3   2:klg,
3   96k,
3   AAC,
3   1.0,
3   s16le,
3   48000

我错过了你想要的输出。这是:

$ for i in {1..3}; do
    aryvar="Audio${i}[*]"    # note the "*" not "@"
    echo "${!aryvar}"
done
0:ita, 96k, AAC, 2.0, s16le, 48000
1:rus, 128k, AAC, 2.0, s16le, 48000
2:klg, 96k, AAC, 1.0, s16le, 48000