如何使用变量在bash中索引$ {array [*]}?

时间:2018-01-31 19:19:16

标签: arrays bash indexing

首先抱歉,因为我的英语可能不好。 我想使用变量来索引数组中的元素,或者使用相同的变量来索引所有元素。例如:

Coordinate c = new Coordinate(40.465, -75.089);

//Display DMS Format
c.FormatOptions.Format = CoordinateFormatType.Degree_Minutes_Seconds;
c.ToString();//N 40º 27' 54" W 75º 5' 20.4"
c.Latitude.ToString();//N 40º 27' 54"
c.Latitude.ToDouble();//40.465

当我使用 var1 $ {array [$ var1]} 中编制索引时,它可以正常工作,但如果我使用 var2 无法正常工作,我收到此错误:

...
var1="1"
var2="*"
array=(one two three for five)

for elem in ${array[$var1]}
do
  echo $elem
done

我很确定该错误与*通配符扩展有关,但我没有找到帮助我解决此问题的答案。那么,我该怎么做呢?

2 个答案:

答案 0 :(得分:4)

*@不被视为数组中的常规元素。迭代键时不会列出它们,并且在通过索引变量间接扩展时不会考虑它们。

bash source code有一个chk_atstar函数可以检查[@][*]是否正在使用,你可以看到它是按字面意思完成的,而不是通过任何扩张:

else if (valid_array_reference (name, 0))
  {
    temp1 = mbschr (name, '[');
    if (temp1 && temp1[1] == '@' && temp1[2] == ']')
      {

如果你真的想这样做,你可以通过变量间接:

arr=(one two three)
index='*'
var="arr[$index]"
echo "${!var}"

尽管您最好不要将这些特殊的数组访问模式视为数组元素。

答案 1 :(得分:1)

我不建议这样做,但为了完整起见,您可以使用eval欺骗扩展订单来实现此目的:

eval items=\${array[$var2]}
for elem in $items
do
    echo $elem
done

这有问题。 eval通常发音为'#34; evil"因为从变量运行代码可能会产生安全隐患。与使用eval相比,通常有更好的方法来完成工作。在这种情况下,您应该考虑一下设计。

如果元素包含嵌入的空格,也会出现问题。添加:

array+=('at the end')

在数组声明之后,你会明白我的意思。

编辑:经过一番考虑,这里有一种方法没有 eval,它支持嵌入空格或制表符(但不支持嵌入的换行符)。漂亮不是:

display_it() {
    if [[ $1 = '*' ]]; then
        oldIFS="$IFS"
        IFS=$'\n'
        echo "${array[*]}"
        IFS="$oldIFS"
    else
        echo "${array[$1]}"
    fi
}

var1="1"
var2="*"
array=(one two three for five)
array+=('at the end')

while read -r elem
do
  echo $elem
done < <(display_it "$var2")

显示器:

one
two
three
for
five
at the end

在循环结束时,您将看到进程替换,其中我调用函数display_it。读取的每个项目由换行符分隔,因此在函数中交换内部字段分隔符(IFS)。