come posso aggiungere (sottrarre, ecc.) due numeri con bash?


90

Riesco a leggere i numeri e l'operazione con:

echo "First number please"
read num1
echo "Second number please"
read num2
echo "Operation?"
read op

ma poi tutti i miei tentativi di aggiungere i numeri falliscono:

case "$op" in
  "+")
    echo num1+num2;;
  "-")
    echo `num1-num2`;;
esac

Correre:

First number please
1
Second mumber please
2
Operation?
+

Produzione:

num1+num2

...o...

echo $num1+$num2;;

# results in: 1+2    

...o...

echo `$num1`+`$num2`;;

# results in: ...line 9: 1: command not found

Sembra che sto ancora ricevendo delle stringhe forse quando provo ad aggiungere add ("2 + 2" invece di "4").


5
Ho modificato il tuo titolo perché questa è una buona domanda generale, e se restringessi il contesto ti saresti reso conto che questo non ha nulla a che fare con caseniente o niente tranne una riga: echo $num+$numpoiché questo riprodurrà esattamente il problema . L'idea di minimizzare il contesto nelle domande di programmazione è spiegata qui: sscce.org
goldilocks,

2
+1 Ciao goldilocks, sì che mi è diventato chiaro in seguito, ma sì, sono totalmente d'accordo con il tuo ragionamento e sì, più una domanda specifica e "singolare" è migliore. Accolgo con favore le tue modifiche :) Grazie :)
Michael Durrant,

Risposte:


117

L'aritmetica nelle shell POSIX viene eseguita con $e doppie parentesi (( )):

echo "$(($num1+$num2))"

Puoi assegnare da quello (sans echo):

num1="$(($num1+$num2))"

C'è anche expr:

expr $num1 + $num2

In scripting $(())è preferibile poiché evita un fork / esegui per il exprcomando.


O anche direttamente echo $(($num1$op$num2))senza coinvolgere case.
arte

Non ci sono casecoinvolti qui.
Riccioli d'oro

1
No, ma hai usato letterale +, quindi avrai bisogno casedell'esterno per gestire la sottrazione separatamente.
arte

1
@manatwork: vuoi dire eliminare casedal codice del PO con echo $(($num1$op$num2))- funzionerà, ma usare il caseè più robusto poiché puoi gestire gli errori con un valore predefinito *.
Riccioli d'oro

+1 per entrambi. Stavo usando case (potrebbe non averlo mostrato all'inizio) ma dato che entrambi avete capito che il problema non riguardava il caso.
Michael Durrant,

13

La risposta esistente è pura bash, quindi sarà più veloce di così, ma può gestire solo numeri interi. Se devi gestire i float, devi usare il programma esterno bc.

$ echo 'scale=4;3.1415+9.99' | bc
13.1315

La scale=4dice bcdi utilizzare quattro cifre decimali. Vedi man bcper maggiori informazioni.


Si noti che mentre bashnon supporta galleggiante aritmetica in virgola con $((...)), molte conchiglie ( ksh93, zsh, yashalmeno) fare. Il vantaggio bcè che supporta una precisione arbitraria mentre l'aritmetica della shell è limitata al doubletipo di processore . Si noti che non è necessario impostare scalequi. Per le aggiunte, il scaleparametro non viene utilizzato. La scala di 3.1415+9.99sarà derivata da quella degli operandi (qui 4).
Stéphane Chazelas,

Come fare la matematica se un valore è 450e l'altro è decimale memorizzato su una variabile $mynumber? Ad esempio 450-$mynumber,.
Sigur,

@sigur echo "450-$mynumber" | bcdovrebbe farlo. Se si desidera che una variabile si espanda, è necessario utilizzare virgolette doppie anziché singole.
evilsoup,

@evilsoup, ora funziona come un fascino. Grazie.
Sigur,

computedval=$(echo 'scale=10;var1-var2' | bc)non funziona, né funzionacomputedval=$(echo 'scale=10;$var1-$var2' | bc)
StatsSorceress

5
echo `expr $a + $b`   
echo `expr $a - $b`   
echo `expr $a \* $b`   
echo `expr $a / $b`   

Nota \prima di *(per la moltiplicazione), l'intera espressione deve essere all'interno dei backquotes `.


1
exprnon è necessario e non è mai necessario acquisire l'output standard di un comando solo per riscriverlo nell'output standard.
Chepner,


1

Puoi anche usare la $[ ... ]struttura. In questo caso, usiamo il meccanismo integrato in Bash, che è più veloce e un po 'più comodo da usare. Poiché sappiamo che tutto tra $ [e] viene trattato come un'espressione, non è necessario anteporre alle variabili $. Allo stesso modo, non abbiamo bisogno di essere sicuri *di trattarlo come uno schema.

num1=2
num2=3
echo $[num1 + num2]
5

0

In base alla sequenza di input richiesti dall'utente, sembra che tu stia utilizzando la notazione polacca inversa.

echo "First number please"
read num1
echo "Second number please"
read num2
echo "Operation?"
read op

Puoi fare di meglio solo per usare dc(calcolatrice da tavolo) direttamente, poiché è quello che serve.

DESCRIPTION
       Dc is a reverse-polish desk calculator which supports unlimited pre-
       cision arithmetic.

Sessione di esempio usando dc:

$ dc
1 2 + p    # This part is typed; the result comes next.
3
q  # This is also typed.
$

Oppure, in modo non interattivo:

$ dc -e '1 2 + p'
3
$
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.