¿Cómo puedo sumar (restar, etc.) dos números con bash?

90

Puedo leer los números y la operación con:

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

pero luego todos mis intentos de agregar los números fallan:

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

Correr:

First number please
1
Second mumber please
2
Operation?
+

Salida:

num1+num2

...o...

echo $num1+$num2;;

# results in: 1+2    

...o...

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

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

Parece que todavía recibo cadenas cuando intento agregar add ("2 + 2" en lugar de "4").

Michael Durrant
fuente
55
Edité su título porque esta es una buena pregunta general, y si redujo el contexto, se habría dado cuenta de que esto no tiene nada que ver caseni nada excepto una línea echo $num+$num, ya que eso reproducirá el problema exactamente . La idea de minimizar el contexto en las preguntas de programación se explica aquí: sscce.org
goldilocks
2
+1 Hola Ricitos de Oro, sí, eso me quedó claro después, pero sí, estoy totalmente de acuerdo con tu línea de razonamiento y sí, cuanto más específica y 'singular' sea una pregunta, mejor. Agradezco sus ediciones :) Gracias :)
Michael Durrant

Respuestas:

117

La aritmética en shells POSIX se realiza con $paréntesis dobles (( )):

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

Puede asignar desde eso (sin echo):

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

También hay expr:

expr $num1 + $num2

En scripting $(())es preferible ya que evita una bifurcación / ejecución para el exprcomando.

encerrada dorada
fuente
O incluso directamente echo $(($num1$op$num2))sin involucrar case.
manatwork
No hay caseinvolucrado aquí.
Ricitos de oro
1
No, pero usaste literal +, por lo que necesitarás el caseexterior para manejar la resta por separado.
manatwork
1
@manatwork: Te refieres a eliminar el casecódigo del OP con echo $(($num1$op$num2))- eso funcionará, pero usarlo casees más robusto ya que puedes manejar los errores de manera predeterminada *.
Ricitos de oro
+1 a los dos. Estaba usando case (podría no haberlo mostrado al principio) pero como ambos se dieron cuenta, el problema no era sobre el caso.
Michael Durrant
13

La respuesta existente es puro bash, por lo que será más rápido que esto, pero solo puede manejar enteros. Si necesita manejar flotadores, debe usar el programa externo bc.

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

El scale=4le dice bcque use cuatro decimales. Ver man bcpara más información.

maldad
fuente
Tenga en cuenta que, si bien bashno soporta la aritmética de punto flotante con $((...)), muchas conchas ( ksh93, zsh, yashpor lo menos) hacer. La ventaja de esto bces que admite precisión arbitraria, mientras que la aritmética de shell está limitada al doubletipo de procesador . Tenga en cuenta que no necesita configurar scaleaquí. Para adiciones, el scaleparámetro no se usa. La escala de 3.1415+9.99se derivará de la de los operandos (aquí 4).
Stéphane Chazelas
¿Cómo hacer los cálculos si un valor es 450y el otro es decimal almacenado en una variable $mynumber? Por ejemplo, 450-$mynumber.
Sigur
@sigur echo "450-$mynumber" | bcdebería hacerlo. Si desea que una variable se expanda, debe usar comillas dobles en lugar de comillas simples.
evilsoup
@evilsoup, ahora funciona de maravilla. Gracias.
Sigur
computedval=$(echo 'scale=10;var1-var2' | bc)no funciona, ni funcionacomputedval=$(echo 'scale=10;$var1-$var2' | bc)
StatsSorceress
5
echo `expr $a + $b`   
echo `expr $a - $b`   
echo `expr $a \* $b`   
echo `expr $a / $b`   

Tenga en cuenta que \antes de *(para la multiplicación), toda la expresión debe estar dentro de las comillas inversas `.

Himani
fuente
1
exprno es necesario, y nunca es necesario capturar la salida estándar de un comando solo para volver a escribirla en la salida estándar.
chepner 01 de
2

minimalista

total=0
((total+=qty))
geekzspot
fuente
1

También puedes usar $[ ... ]estructura. En este caso, utilizamos un mecanismo integrado en Bash, que es más rápido y un poco más cómodo de usar. Como sabemos que todo entre $ [y] se trata como una expresión, no necesitamos preceder a las variables con $. Del mismo modo, no necesitamos asegurarnos *de tratarlo como un patrón.

num1=2
num2=3
echo $[num1 + num2]
5
jedi
fuente
0

Según la secuencia de entradas que solicita del usuario, parece que está utilizando la notación de pulido inverso.

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

Puede hacerlo mejor solo para usar dc(calculadora de escritorio) directamente, ya que para eso es.

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

Ejemplo de sesión usando dc:

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

O, de forma no interactiva:

$ dc -e '1 2 + p'
3
$
Comodín
fuente