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

4 回答 4

2

我认为你的循环表现得很有趣,因为它应该从 i = 1 开始并转到 i = ${#*}。${@:0:1} 的扩展给出了 file1,${@:1:1} 也是如此。

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

于 2012-04-15T00:04:55.720 回答
1

您正在遍历从 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
于 2012-04-15T00:08:00.480 回答
1

$@不是一个真正的数组 - 它是一个外壳“特殊参数”,你需要比其他数组更加小心。

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

这是相关文档(我的粗体强调):

${参数:偏移:长度}

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

位置参数是, $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]}
于 2012-04-15T00:11:12.600 回答
0

实际上,您得到的是第二个元素,但是您的循环在 [0] 和 [1] 中放置了相同的值。

我不确定您要做什么,但是迭代参数然后为数组保留一个单独的计数器可能会更容易。

n=0
for i in "$@"; do
  . . .
  n=$(($n + 1))
done
于 2012-04-14T23:43:44.340 回答