这是我的剧本:
#!/bin/bash
#adding values in an array
function addarray {
local sum=0
local newarray
newarray=(`echo "$@"`)
for value in $newarray
do
sum=$[ $sum+$value ]
done
echo $sum
}
myarray=(1 2 3 4 5)
echo "the origin array is : ${myarray[*]}"
arg1=`echo ${myarray[*]}`
echo $arg1
result=`addarray arg1`
echo "the result is $result
这里是errormessage
the origin array is : 1 2 3 4 5
1 2 3 4 5
test11: line 9: 1 2 3 4 5: syntax error in expression (error token is "2 3 4 5")
the result is
我的linux版本是centos 7.0,当我只在脚本中使用循环而不是函数时,进程时不会有错误
答案 0 :(得分:2)
这里有许多混淆的来源。首先,每当你在反引号中使用echo somethingorother
之类的东西时,你就会做一些奇怪而毫无意义的事情;它接受字符串(在我的示例中是另一个),将其转换为输出(echo
命令),然后反引号捕获输出并将其转换回字符串。最终结果:echo
和反引号有效地相互抵消,然后您返回原始字符串。嗯,大多数;有几件奇怪的事情可能会让事情搞得一团糟。只需跳过echo
和反引号,直接使用字符串。所以,例如,这一行:
arg1=`echo ${myarray[*]}`
可以替换为
arg1=${myarray[*]}
而且BTW名称arg1与该变量包含的内容或它的使用方式(好吧,等等)不匹配。它包含所有 myarray
的元素,而不仅仅是第一个元素。它似乎也意味着它的值将作为所有的参数传递给addarray
(虽然发生了不同的事情,因为我会稍微解释一下)。
其次,您处理错误的数组。接受我刚才提到的命令;它接受数组的所有元素,并将它们(在它们之间有空格)组合成一个字符串,并将该字符串存储在arg1
中。因此,myarray
是数组("1" "2" "3" "4" "5")
,但arg1
只是单个字符串" 1 2 3 4 5"。
addarray
函数中存在一些类似的混淆。使用以下函数将函数的参数存储为数组:
newarray=(`echo "$@"`)
(好吧,大多数情况下 - 这实际上是接受参数,小心地将每个参数传递给echo
作为参数,它们将它们之间的空格粘在一起,然后将输出分成基于空格和每个单词的单词存储为newarray
的元素。如果参数中有任何空格,那么这些空格现在将被拆分为单独的数组元素,这通常是一个错误。更糟糕的是,如果任何参数包含shell通配符,它们就是#39 ; \ n \ n会被匹配文件列表替换。这不是问题,但有时你会尝试将" *"传递给函数来告诉它繁殖,并且它最终会出现一个文件名列表并且非常困惑。正确的方法是newarray=("$@")
。)
然后你引用newarray
就好像它只是一个普通的字符串变量:
for value in $newarray
这只需要newarray
的第一个元素(您需要${newarray[@]}
或${newarray[*]}
来获取所有元素)。然后,由于它不是双引号,它会将其拆分为基于空格的单词,然后将任何通配符扩展为匹配文件名列表。获取数组的所有元素时,您几乎总是希望使用"${newarray[@]}"
来单独处理每个元素,而不是单词分割或通配符扩展。
现在最大的问题。这一行:
result=`addarray arg1`
运行函数addarray
,并将参数" arg1"传递给它。不是变量arg1
,而是它的值(" 1 2 3 4 5"),只是文本字符串" arg1"。因此,在函数内部,newarray
只获得一个元素," arg1&#34 ;;并且for
循环运行一次,value
设置为" arg1"。这意味着循环中的行:
sum=$[ $sum+$value ]
扩展为:
sum=$[ 0+arg1 ]
但由于$[ ]
的内部是算术上下文,因此字符串" arg1"被隐式地视为变量名称并扩展为其内容,给出:
sum=$[ 0+1 2 3 4 5 ]
其中" 2 3 4 5"部分没有意义,给出你看到的错误。
现在让我添加一些风格注释:在声明函数时,funcname()
比function funcname
更标准和可移植。使用$(( ))
代替其过时的等效文件$[ ]
。使用$( )
代替反引号来捕获命令的输出 - 它更容易阅读,反引号有一些奇怪的语法后果可能会让你感到沮丧。最后,最好将变量引用放在双引号中(例如echo "$sum"
而不是echo $sum
),即使它不是绝对必要的。
这是更正后的版本:
#!/bin/bash
#adding values in an array
addarray() {
local sum=0
local newarray
newarray=("$@") # This keeps each argument a separate array element
for value in "${newarray[@]}" # This iterates over the elements cleanly
do
sum=$(( sum+value )) # In arithmetic context, $ is not needed for variables
done
echo "$sum"
}
myarray=(1 2 3 4 5)
echo "the origin array is : ${myarray[*]}" # [*] mashes the elements together with spaces between, but that's ok here
result=$(addarray "${myarray[@]}") # Pass each array element as a separate argument
echo "the result is $result"
哦,还有一个建议:shellcheck.net非常适合指出脚本中常见的错误和不良做法。在您学习的同时,通过它来运行您的脚本,它可以帮助您避免养成各种不良习惯。