Bash'da isteğe bağlı olarak argüman nasıl yapılır?


13

Aşağıdaki 9 bağımsız değişkeni olan fonksiyon:

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

Sonraki (3..9) için ikinci argüman isteğe bağlı bir argüman haline getirmek istiyorum .

İşlevi 2 argümanla çağırdığımda hata alıyorum:

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

Not BOLD : birinci bağımsız değişken ve ikinci bağımsız değişken zorlama bağımsız değişkenleridir ve işlev için isteğe bağlı değildir. Ben sadece sonraki ikinci argüman isteğe bağlıdır ve 2 argümandan daha az fonksiyon çağırdığınızda fonksiyon sonuç vermemelidir.

Yanıtlar:


22

Boşluk içeren bağımsız değişkenler iletmezseniz:

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

Etki:

$ sum 1 2 3
6

Açıklama:

  1. <<<"some string"yalnızca "some string"girdi olarak beslenir . Bunu kısayol olarak düşünün echo "some string" |. Buraya Here String denir .
  2. "$@"boşluklarla ayrılmış tüm konum parametrelerine genişler. Eşdeğerdir "$1 $2 ...".
  3. Böylece, dış tarafından değerlendirilen tr ' ' '+' <<<"$@"çıktılar ."$1+$2+$3..."$(( ))
  4. [[ -n $2 ]]ikinci parametrenin boş olup olmadığını test eder. Sen yerini alabilir [[ -n $2 ]] &&ile [[ -z $2 ]] ||.

Diğer yol:

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

Açıklama:

  1. $*gibi olan $@parametreler boşluklarla ayrılmış uygun değildirler, fakat ilk karakter ile iç alan ayırıcı ( IFS) . İle IFS=+"$ 1 + $ 2 + ..." değerine genişler. Bkz. $ * Ve $ @ arasındaki fark nedir?
  2. Biz set IFSyüzden ana kabuk etkilenmemesini bir kabuktaki (çevreleyen parantezler unutmayın) içinde. IFSvarsayılan olarak: \t\n(boşluk, sekme, yeni satır). Bu localdeğişkenleri kullanmaya bir alternatiftir .

Şimdi sorunuzu cevaplamak için:

Herhangi bir değişken veya parametre için varsayılan bir değer kullanabilirsiniz . Ya:

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

Veya:

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

6
Şık! Yorumların ücretsiz övgü ve teşekkürler için olmadığını biliyorum, ama bu çözüm sadece ... kötü! :-)
— zwets

17

shiftOperatöre bir göz atın . Bağımsız değişken 2 ve ileriye 1 ve sonraki konumlara geçer ve bağımsız değişken 1'i atar.

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

4

sumBağımsız değişkenler olmadan çağrıldığında sonlanan özyinelemeli bir tanım kullanabilirsiniz . testTartışma olmadan değerlendirilen gerçeği kullanırız false.

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

3

Bunu dene:

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

Bu çıkış 12 ve 30'u verir.

$@"Parametre", parametreye karşılık gelir, parametre $#sayısını, bu durumda 3 veya 11 döndürür.

Linux redhat 4 üzerinde test edildi


2

Sadece küçük bir döngü kullanabilirsiniz:

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

Şahsen olsa, ben sadece kullanmayı tercih ediyorum perlya awkyerine:

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

veya

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

2

$ 1 ila $ 9 için varsayılan değerler olarak 0 kullanın:

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

Gönderen 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.

Örnekler:

$ SUM

Toplam 0

$ SUM 1 2 

Toplam 3

$ SUM 1 1 1 1 1 1 1 1 1 

Toplam 9


Awk ile aynı çıktı:

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

1

Aynı zamanda kendi çözümümü denedim ve buldum:

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

$ SUM 4 6 5
The sum is 15

Ama @ muru'nun cevabı iyi.


+1: Boş parametreleri sıfıra değerlendirmek için iki aritmetik genişletmenin ilginç kullanımı .
— muru

1
muru teşekkürler, ama bu durumda cevabım 9'dan fazla argüman kullanmıyoruz ve 9'dan fazla geçmek için argüman grubunu kullanmalıyız. Mükemmel cevabınız için teşekkür ederim.
— αғsнιη
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.