web-dev-qa-db-fra.com

Comment rendre l'argument optionnel dans bash?

En dessous, fonction avec 9 arguments:

SUM() { 
    echo "The sum is $(($1+$2+$3+$4+$5+$6+$7+$8+$9))"
}

Je veux faire le les deuxièmes arguments à la suite (3..9) deviennent des arguments optionnels.

Lorsque j'appelle la fonction avec 2 arguments, j'obtiens une erreur:

SUM 3 8
bash: 3+8+++++++: syntax error: operand expected (error token is "+")

Note BOLD: le premier argument et le second argument sont arguments de force et non facultatifs pour function. Je veux seulement que le second argument soit optionnel et lorsque j'appelle la fonction moins de 2 arguments, la fonction ne doit pas donner de résultat.

13
αғsнιη

Si vous ne passez pas d'arguments avec des espaces:

sum() {  
[[ -n $2 ]] && echo $(( $(tr ' ' '+' <<<"$@") ))
}

Effet:

$ sum 1 2 3
6

Explication:

  1. <<<"some string" alimente uniquement "some string" en tant qu'entrée. Pensez-y comme un raccourci pour echo "some string" |. Cela s'appelle un Here String .
  2. "$@" se développe dans tous les paramètres de position, séparés par des espaces. C'est équivalent à "$1 $2 ...".
  3. Par conséquent, tr ' ' '+' <<<"$@" génère "$1+$2+$3...", qui est évalué par la $(( )) extérieure.
  4. [[ -n $2 ]] teste si le deuxième paramètre est non vide. Vous pouvez remplacer [[ -n $2 ]] && par [[ -z $2 ]] ||.

Autrement:

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

Explication:

  1. $* est identique à $@, sauf que les paramètres ne sont pas séparés par des espaces, mais par le premier caractère du séparateur de champ interne (IFS) . Avec IFS=+, il devient "$ 1 + $ 2 + ...". Voir Quelle est la différence entre $ * et $ @?
  2. Nous avons défini IFS dans un sous-shell (notez les parenthèses qui l'entourent) afin que le shell principal ne soit pas affecté. IFS est, par défaut: \t\n (espace, tabulation, nouvelle ligne). C'est une alternative à l'utilisation de variables local.

Maintenant pour répondre à votre question:

Vous pouvez utiliser un valeur par défaut pour toute variable ou paramètre. Non plus:

SUM() { 
 echo "The sum is $(($1+$2+${3:-0}+${4:-0}+${5:-0}+${6:-0}+${7:-0}+${8:-0}+${9:-0}))" || false
}

Ou:

SUM() { 
 echo "The sum is $(($1+$2+${3:=0}+${4:=0}+${5:=0}+${6:=0}+${7:=0}+${8:=0}+${9:=0}))" || false
}
22
muru

Examinez l'opérateur shift. Il déplacera les arguments 2 et suivants aux positions 1 et suivantes, en écartant l'argument 1.

sum () {
    local total=0;
    while [ $# -gt 0 ]; do
        total=$(($total + $1))
        shift
    done
    echo $total
}
17
zwets

Vous pouvez utiliser une définition récursive qui se termine lorsque sum est invoqué sans argument. Nous utilisons le fait que test sans arguments est évalué à false.

sum () {
    test $1 && echo $(( $1 + $(shift; sum $@) )) || echo 0
}
4
zwets

Essaye ça:

SUM () {
 [ $# -lt "2" ] && return 1
 for par in $@; do
   local sum=`expr $sum + $par`
 done
 echo $sum
 return 0
}

SUM 3 4 5
SUM 3 4 5 1 1 1 1 2 3 4 5

Cela produira les sorties 12 et 30.

$@ fait référence au paramètre, $# renvoie le numéro du paramètre, dans ce cas 3 ou 11.

Testé sur Linux RedHat 4

3
Lety

Vous pouvez simplement utiliser une petite boucle:

sum(){
    t=0;
    for i in "$@"; do t=$((t + i )); done
    echo $t;
}

Personnellement, j’utiliserais plutôt Perl ou awk:

sum(){
 echo "$@" | Perl -lane '$s+=$_ for @F; print $s'
}

ou

sum(){
 echo "$@" | awk '{for(i=1; i<=NF; i++){k+=$i} print k}'
}
2
terdon

Utilisez 0 comme valeurs par défaut pour 1 $ à 9 $:

SUM() { 
    echo "The sum is $((${1:-0}+${2:-0}+${3:-0}+${4:-0}+${5:-0}+${6:-0}+${7:-0}+${8:-0}+${9:-0}))"
}

De man bash:

${parameter:-Word}
    Use Default Values. If parameter is unset or null, the expansion
    of Word is substituted. Otherwise, the value of parameter is
    substituted.

Exemples:

$ SUM

La somme est 0

$ SUM 1 2 

La somme est 3

$ SUM 1 1 1 1 1 1 1 1 1 

La somme est 9


SUM() {
  echo -e ${@/%/\\n} | awk '{s+=$1} END {print "The sum is " s}'
}
2
Cyrus

C'est aussi ma propre solution que j'ai essayée et trouvée:

SUM() { 
    echo "The sum is $(($1+$2+$[$3]+$[$4]+$[$5]+$[$6]+$[$7]+$[$8]+$[$9]))"
 }

$ SUM 4 6 5
The sum is 15

Mais réponse de @ mur c'est bien.

1
αғsнιη