下面的函数有 9 个参数:
SUM() {
echo "The sum is $(($1+$2+$3+$4+$5+$6+$7+$8+$9))"
}
我想让next(3..9) 的第二个参数成为可选参数。
当我使用 2 个参数调用该函数时出现错误:
SUM 3 8
bash: 3+8+++++++: syntax error: operand expected (error token is "+")
注意粗体:第一个参数和第二个参数是强制参数并且对于函数来说不是可选的。我只希望下一个函数的第二个参数是可选的,并且当我调用少于 2 个参数的函数时,该函数必须不返回结果。
答案1
如果您不传递带有空格的参数:
sum() {
[[ -n $2 ]] && echo $(( $(tr ' ' '+' <<<"$@") ))
}
影响:
$ sum 1 2 3
6
解释:
<<<"some string"
仅"some string"
作为输入。可以将其视为 的简写echo "some string" |
。它被称为这里字符串。"$@"
扩展为所有位置参数,以空格分隔。它相当于"$1 $2 ..."
。- 因此,
tr ' ' '+' <<<"$@"
输出"$1+$2+$3..."
,由外部进行评估$(( ))
。 [[ -n $2 ]]
测试第二个参数是否非空。您可以[[ -n $2 ]] &&
用替换[[ -z $2 ]] ||
。
其他方式:
sum() {
[[ -n $2 ]] && (IFS=+; echo $(( $* )))
}
解释:
$*
类似于$@
,只是参数不是用空格分隔,而是用第一个字符分隔内部字段分隔符 (IFS
)。使用IFS=+
,它扩展为“$1+$2+...”。请参阅$* 和 $@ 有什么区别?- 我们设置
IFS
一个子 shell(注意周围的括号),这样主 shell 就不会受到影响。IFS
默认情况下是:(\t\n
空格、制表符、换行符)。这是使用变量的替代方法local
。
现在回答你的问题:
您可以使用默认值对于任何变量或参数。可以:
SUM() {
echo "The sum is $(($1+$2+${3:-0}+${4:-0}+${5:-0}+${6:-0}+${7:-0}+${8:-0}+${9:-0}))" || false
}
或者:
SUM() {
echo "The sum is $(($1+$2+${3:=0}+${4:=0}+${5:=0}+${6:=0}+${7:=0}+${8:=0}+${9:=0}))" || false
}
答案2
看一下shift
运算符。它将把参数 2 及以后移动到位置 1 及以后,并丢弃参数 1。
sum () {
local total=0;
while [ $# -gt 0 ]; do
total=$(($total + $1))
shift
done
echo $total
}
答案3
您可以使用递归定义,当sum
不带参数调用时,该定义终止。我们利用test
不带参数的计算结果为的事实false
。
sum () {
test $1 && echo $(( $1 + $(shift; sum $@) )) || echo 0
}
答案4
你可以使用一个小循环:
sum(){
t=0;
for i in "$@"; do t=$((t + i )); done
echo $t;
}
不过就我个人而言,我还是会使用perl
或者awk
代替:
sum(){
echo "$@" | perl -lane '$s+=$_ for @F; print $s'
}
或者
sum(){
echo "$@" | awk '{for(i=1; i<=NF; i++){k+=$i} print k}'
}