UNIX KSH/BASH 使用数组通过引用调用(在 GNU bash 4.2 中)

UNIX KSH/BASH 使用数组通过引用调用(在 GNU bash 4.2 中)

我是 Unix shell 脚本新手 我的代码如下:

  i=0
for var in 'a' 'b' 'c' 'd' 'e'
do
  content[i]=var
  ((i=`expr i+1`))
done
a=10
b=50
c=40
d=90
e=100
Now I wanted to print the local variables contents using array into the function

print_array
{
echo "${content[0]}"
echo "${content[1]}"
echo "${content[2]}"
echo "${content[3]}"
echo "${content[4]}"
} 

我想要做的数组内容是 {a,b,c,d,e} 并且有一个名为 a,b,c,d,e 的局部变量,带有一些分配的值我想通过使用打印这些局部变量数组的名称,因为数组元素和局部变量元素的名称相同,因此我尝试通过尝试 $ 和 array_names 的多种组合来通过引用调用,但不起作用

答案1

所以我首先定义一个间接打印函数......

_print() while [ "$#" -ne 0 ]
         do    printf '$%s = %d\n' \
                       "$1" "$(($1))"
               shift
         done

接下来我将设置数组并递增......

arr=( a b c d e ); i=0
for var in "${arr[@]}"
do  : "$(($var=(i+=10)))"
done

所以现在 的值$a是 10 和$b20 等等。最后只剩下打印了...

_print "${arr[@]}"

...打印到标准输出...

$a = 10
$b = 20
$c = 30
$d = 40
$e = 50

所有这些之所以有效,是因为 shell 处理$((数学))扩展的方式 - 它们基本上是evals。在算术展开式中,shell第一的扩大任何在尝试进行数学计算之前进行其他有效的 shell 扩展 - 使实际数学成为最后的任务。

这意味着如果您这样做:

i=a a=10; echo "$(($i))" 

打印的结果是10因为 shell 扩展了$ito get的值a然后求值结果作为整数参考。

上面的代码可以在任何兼容 POSIX 的 shell 中运行。

这意味着我也可能做了......

i=10
for var in a b c d e
do  arr[($var=i*${#arr[@]}+i)/i]=$var
done

$var...同时处理数组赋值、索引求值和整数赋值,因为命名 shell 数组的[索引]括号(在支持它们的 shell 中)与数​​学表达式的$((扩展括号相同。))

运行包含在命令中的上述代码ksh -xc会将以下调试输出打印到标准错误:

+ arr[1]=a
+ arr[2]=b
+ arr[3]=c
+ arr[4]=d
+ arr[5]=e

从那里我可以做:

echo "$((${arr[1]}))"
echo "$((a))"

...打印...

10
10

...因为它们在支持命名数组的 shell 中求值相同。然而,在不...

echo 'arr=(a b c d e)' | bash -x
+ arr=(a b c d e)     #bash traces the successful command to stderr
echo 'arr=(a b c d e)' | sh -x
sh: 1: Syntax error: "(" unexpected   #sh traces something else

所以在_print()函数中我只是shift在位置参数上(代表真正的便携式贝壳"$@"阵列)虽然有任何并且printf......

  1. 首先是$美元符号。
  2. 然后%s将 tring 值存储在我的$1st 位置参数中。
  3. 然后是=等号。
  4. 最后将值存储在值存储在我的$(($1))第一个位置参数。

当函数shift的参数消失时,第一个位置参数不断地被下一个位置参数替换,直到$#位置参数计数等于 0 并且函数返回。

在运行函数之前,当我初始化数组及其组成的间接变量时,其工作方式如下:

  • for var in "${arr[@]}"

    • shell 将扩展[@]列表参数和[*]该列表的单个串联。如果扩展没有被引用的话可能也扩展到一个列表 - 取决于完成时[*]是否有值以及当前如何配置 ilename 扩展 - 但如果这样做,它可能不会按照您想要的方式进行。$IFSset -f
  • : "$(($var=(i+=10)))"

    • 中的每个值依次${arr[@]}分配给 的值。然后被扩展$var$(($var=(i+=10)))第一的$var对于like中的值$((a=(i+=10))),最后完成所有数学运算 - 首先递增$i10,然后将值赋给$ito $a

答案2

尝试

#i=0
for var in 'a' 'b' 'c' 'd' 'e'
do
  content[${#content[*]}]=$var  # or content[i++]=$var
done
# or just content=( 'a' 'b' 'c' 'd' 'e' )
a=10
b=50
c=40
d=90
e=100
for i in "${#content[@]}"
do
  echo ${!i}
done

答案3

如果我理解正确的话,您需要在变量访问中进行间接访问,例如bash.有了这个代码:

content=( a b c d e )

a=10
b=50
c=40
d=90
e=100

echo "${!content[0]}"
echo "${!content[1]}"
echo "${!content[2]}"
echo "${!content[3]}"
echo "${!content[4]}"

你会得到这样的结果:

10
50
40
90
100

这里的关键是bash具体的变量扩展访问方法"${! ... }"

相关内容