Come posso aggiungere numeri in uno script bash

Ho questo script bash e ho avuto un problema nella riga 16. Come posso prendere il risultato precedente della riga 15 e aggiungerlo alla variabile nella riga 16?

#!/bin/bash num=0 metab=0 for ((i=1; i<=2; i++)); do for j in `ls output-$i-*`; do echo "$j" metab=$(cat $j|grep EndBuffer|awk '{sum+=$2} END { print sum/120}') (line15) num= $num + $metab (line16) done echo "$num" done 

Per numeri interi :

  • Usa l’espansione aritmetica : $((EXPR))

     num=$((num1 + num2)) num=$(($num1 + $num2)) # also works num=$((num1 + 2 + 3)) # ... num=$[num1+num2] # old, deprecated arithmetic expression syntax 
  • Utilizzando l’utilità expr esterna. Si noti che questo è necessario solo per sistemi molto vecchi.

     num=`expr $num1 + $num2` # whitespace for expr is important 

Per il punto mobile :

Bash non supporta direttamente questo, ma ci sono un paio di strumenti esterni che puoi usare:

 num=$(awk "BEGIN {print $num1+$num2; exit}") num=$(python -c "print $num1+$num2") num=$(perl -e "print $num1+$num2") num=$(echo $num1 + $num2 | bc) # whitespace for echo is important 

Puoi anche usare la notazione scientifica (es: 2.5e+2 )


Insidie ​​comuni :

  • Quando si imposta una variabile, non è ansible avere spazi bianchi su entrambi i lati di = , altrimenti imporrà alla shell di interpretare la prima parola come il nome dell’applicazione da eseguire (ad esempio: num= o num )

    num= 1 num =2

  • bc ed expr aspettano ogni numero e operatore come argomento separato, quindi lo spazio bianco è importante. Non possono elaborare argomenti come 3+ +4 .

    num=`expr $num1+ $num2`

Usa l’espansione aritmetica $(( )) .

 num=$(( $num + $metab )) 

Vedi http://tldp.org/LDP/abs/html/arithexp.html per maggiori informazioni.

Ci sono mille modi per farlo. Ecco uno che usa dc :

 dc <<<"$num1 $num2 + p" 

Ma se è troppo bash per te (o per la portabilità), potresti dire

 echo $num1 $num2 + p | dc 

Ma forse sei una di quelle persone che pensano che l'RPN sia icky e strano; non ti preoccupare! bc è qui per te:

 bc <<< "$num1 + $num2" echo $num1 + $num2 | bc 

Detto questo, ci sono alcuni miglioramenti non correlati che potresti apportare al tuo script

 #!/bin/bash num=0 metab=0 for ((i=1; i<=2; i++)); do for j in output-$i-* ; do # for can glob directly, no need to ls echo "$j" # grep can read files, no need to use cat metab=$(grep EndBuffer "$j" | awk '{sum+=$2} END { print sum/120}') num=$(( $num + $metab )) done echo "$num" done 

MODIFICARE:

Come descritto in BASH FAQ 022 , bash non supporta nativamente i numeri in virgola mobile. Se è necessario sumre i numeri in virgola mobile è necessario l'uso di uno strumento esterno (come bc o dc ).

In questo caso la soluzione sarebbe

 num=$(dc <<<"$num $metab + p") 

Per aggiungere accumuli numeri a virgola mobile eventualmente in num .

In bash,

  num=5 x=6 (( num += x )) echo $num # ==> 11 

Nota che bash può gestire solo l’aritmetica dei numeri interi, quindi se il tuo comando awk restituisce una frazione, allora ti consigliamo di riprogettare: ecco il tuo codice riscritto un po ‘per fare tutta la matematica in awk.

 num=0 for ((i=1; i<=2; i++)); do for j in output-$i-*; do echo "$j" num=$( awk -vn="$num" ' /EndBuffer/ {sum += $2} END {print n + (sum/120)} ' "$j" ) done echo "$num" done 

Mi piace molto anche questo metodo, meno ingombro:

 count=$[count+1] 

Ho sempre dimenticato la syntax, quindi vengo su google, ma non trovo mai quello con cui ho familiarità: P. Questo è il più pulito per me e più fedele a quello che mi aspetterei in altre lingue.

 i=0 ((i++)) echo $i; 
  #!/bin/bash read X read Y echo "$(($X+$Y))" 

È necessario dichiarare il metab come numero intero e quindi utilizzare la valutazione aritmetica

 declare -i metab num ... num+=metab ... 

Per ulteriori informazioni, consultare https://www.gnu.org/software/bash/manual/html_node/Shell-Arithmetic.html#Shell-Arithmetic

Un altro modo POSIX compatibile con bash in bash , che può essere definito come una funzione in .bashrc per tutti gli operatori aritmetici di convenienza.

 addNumbers () { local IFS='+' printf "%s\n" "$(( $* ))" } 

e basta chiamarlo in linea di comando come,

 addNumbers 1 2 3 4 5 100 115 

L’idea è di usare l’ Input-Field-Separator (IFS) , una variabile speciale in bash usata per la divisione delle parole dopo l’espansione e per dividere le linee in parole. La funzione modifica il valore localmente per utilizzare il carattere di suddivisione della parola come operatore sum + .

Ricordare che l’ IFS è cambiato localmente e NON ha effetto sul comportamento IFS predefinito al di fuori dell’ambito della funzione. Un estratto dalla pagina man bash ,

La shell considera ogni carattere di IFS come un delimitatore e divide i risultati delle altre espansioni in parole su questi caratteri. Se IFS non è impostato, o il suo valore è esattamente, l’impostazione predefinita, quindi le sequenze di,, e all’inizio e alla fine dei risultati delle espansioni precedenti vengono ignorate e qualsiasi sequenza di caratteri IFS non all’inizio o alla fine serve a delimitare parole.

"$(( $* ))" Rappresenta l’elenco degli argomenti passati a essere divisi da + e in seguito il valore di sum viene emesso utilizzando la funzione printf . La funzione può essere estesa per aggiungere spazio anche ad altre operazioni aritmetiche.

 #!/bin/bash num=0 metab=0 for ((i=1; i<=2; i++)); do for j in `ls output-$i-*`; do echo "$j" metab=$(cat $j|grep EndBuffer|awk '{sum+=$2} END { print sum/120}') (line15) let num=num+metab (line 16) done echo "$num" done