如何使 bash 中的参数成为可选的?

如何使 bash 中的参数成为可选的?

下面的函数有 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

解释:

  1. <<<"some string""some string"作为输入。可以将其视为 的简写echo "some string" |。它被称为这里字符串
  2. "$@"扩展为所有位置参数,以空格分隔。它相当于"$1 $2 ..."
  3. 因此,tr ' ' '+' <<<"$@"输出"$1+$2+$3...",由外部进行评估$(( ))
  4. [[ -n $2 ]]测试第二个参数是否非空。您可以[[ -n $2 ]] &&用替换[[ -z $2 ]] ||

其他方式:

sum() {
[[ -n $2 ]] && (IFS=+; echo $(( $* )))
}

解释:

  1. $*类似于$@,只是参数不是用空格分隔,而是用第一个字符分隔内部字段分隔符 ( IFS)。使用IFS=+,它扩展为“$1+$2+...”。请参阅$* 和 $@ 有什么区别?
  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}'
}

相关内容