Bash参数数组操作问题

4

我有一个关于我的第一个bash脚本的问题。我在for循环中填充了一个数组,但当我尝试从中获取一个项目时,我总是得到第一个元素。

for (( i = 0; i < ${#*}; i++ )); do
hash=$(md5 -q ${@:$i:1})
modifiedNames[$i]=${@:$i:1}$hash 
done

echo ${modifiedNames[1]}

例如,如果我像这样调用我的脚本:./script.sh file1 file2,那么我会得到file1 [file1hash]。
提前感谢!
4个回答

2
我觉得你的循环出现问题是因为它应该从 i = 1 开始,到 i = ${#*} 结束。${@:0:1} 的展开结果是 file1,${@:1:1} 也是一样。
尝试使用 for (( i = 1; i <= ${#*}; i++ ))

1

你正在迭代从0开始的参数数组,其中0是命令名称。因此,如果您像这样调用脚本./script.sh file1 file2,那么:

${@} = array(
   [0] = ./script,
   [1] = file1,
   [2] = file2
)

所以你会得到:

modifiedNamed = array(
   [0] = md5(./script),
   [1] = md5(file1)
)

你应该将 for 循环的索引更改为:

for (( i = 1; i <= ${#*}; i++ )); do

1

$@ 不是一个真正的数组 - 它是一个 shell 的 "特殊参数",你需要比其他数组更加小心地处理它。

你看到的行为的原因是,当 parameter@ 时,${parameter:length:offset} 语法的确切行为是特殊情况,并且该行为与如果 @ 是一个真正的数组所得到的行为不一致。

这里是相关的文档(粗体 是我自己加的强调):

${parameter:offset:length}

... 如果 parameter 是 @,则结果是从 offset 开始的 length位置参数。如果 parameter 是 @,则结果是从 offset 开始的 length 个位置参数。...

位置参数$0$1$2等等,因此使用这种语法时,它的行为就像$@包含脚本名称($0)以及脚本参数($1$2等等)。这与"$@"扩展为"$1" "$2" ...不一致,但这就是生活。

您应该能够通过创建一个新数组而不是直接使用$@来简化事情(并修复脚本),即

new_array=("$@")
for (( i = 0; i < ${#new_array}; i++ )); do
    hash=$(md5 -q ${new_array[@]:$i:1})
    modifiedNames[$i]=${new_array[@]:$i:1}$hash 
done

echo ${modifiedNames[1]}

0

实际上,您正在获取第二个元素,但是您的循环将相同的值放入[0]和[1]中。

我不确定您想要做什么,但遍历参数然后为数组保留单独的计数器可能会更容易。

n=0
for i in "$@"; do
  . . .
  n=$(($n + 1))
done

好的,但是为什么循环会这样呢?我看不出来它为什么会将相同的值放入数组项中。 - Alexander Oleynikov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接