¿Cómo puedo hacer la división con variables en un shell de Linux?


136

Cuando ejecuto comandos en mi shell como se muestra a continuación, devuelve un expr: non-integer argumenterror. ¿Alguien puede explicarme esto?

$ x=20
$ y=5
$ expr x / y 
expr: non-integer argument

44
@ShivanRaptor Si bien se podría argumentar que la pregunta es una pregunta RTFM, sin duda es una pregunta de programación de shell válida. También es una pregunta razonable para alguien que proviene de idiomas que no requieren desreferenciación (por ejemplo, Ruby o JavaScript). Debería dejarse abierto.
Todd A. Jacobs

66
@ShivanRaptor No, este es el tema aquí. Se trata de programar en Bash. Unix / Linux es principalmente para usar el sistema, no para programar. Ahora, las secuencias de comandos de shell abarcan el límite entre la programación y el uso del sistema, por lo que esto podría ser un tema en cualquiera de los sitios. Si hubiera una pregunta sobre "cómo configuro las redes", eso definitivamente pertenecería a Unix / Linux. Si se tratara de una combinación de teclas interactiva en Bash, eso también pertenecería allí. Pero una pregunta acerca de las secuencias de comandos de shell definitivamente es un tema aquí y allí.
Brian Campbell

Vea mi respuesta aquí, que ilustra la sustracción y división de variables $ BASH, usando una llamada a Python desde el shell (para convertir int a float ...): stackoverflow.com/questions/8385627/…
Victoria Stuart

Respuestas:


195

Esas variables son variables de shell. Para expandirlos como parámetros a otro programa ( es decir expr ), debe usar el $prefijo:

expr $x / $y

La razón por la que se quejó es porque pensó que estaba tratando de operar con caracteres alfabéticos ( es decir, no enteros)

Si está utilizando el shell Bash, puede lograr el mismo resultado utilizando la sintaxis de expresión:

echo $((x / y))

O:

z=$((x / y))
echo $z

1
Puede averiguar mucho leyendo la página de manual de bash. Escriba man bashen el indicador ( qpara salir)
paddy

62
Debe señalarse en algún lugar de esta página que la mayoría (si no todos) los shells GNU / Linux solo realizan operaciones enteras .
Skippy le Grand Gourou

35

Creo que ya se mencionó en otros hilos:

calc(){ awk "BEGIN { print "$*" }"; }

entonces simplemente puedes escribir:

calc 7.5/3.2
  2.34375

En tu caso será:

x=20; y=3;
calc $x/$y

o si lo prefiere, agregue esto como un script separado y póngalo disponible en $ PATH para que siempre lo tenga en su shell local:

#!/bin/bash
calc(){ awk "BEGIN { print $* }"; }

44
También puedes usarecho '1 / 3' | bc -l
Eugene

19

¿Por qué no usar let; Me resulta mucho más fácil. Aquí hay un ejemplo que puede encontrar útil:

start=`date +%s`
# ... do something that takes a while ...
sleep 71

end=`date +%s`
let deltatime=end-start
let hours=deltatime/3600
let minutes=(deltatime/60)%60
let seconds=deltatime%60
printf "Time spent: %d:%02d:%02d\n" $hours $minutes $seconds

Otro ejemplo simple: calcule el número de días desde 1970:

let days=$(date +%s)/86400

15

Hacer referencia a variables de Bash requiere expansión de parámetros

El shell predeterminado en la mayoría de las distribuciones de Linux es Bash. En Bash, las variables deben usar un prefijo de signo de dólar para la expansión de parámetros . Por ejemplo:

x=20
y=5
expr $x / $y

Por supuesto, Bash también tiene operadores aritméticos y una sintaxis de expansión aritmética especial , por lo que no es necesario invocar el binario expr como un proceso separado. Puede dejar que el shell haga todo el trabajo de esta manera:

x=20; y=5
echo $((x / y))

Consulte Expansión aritmética y Aritmética de shell en el Manual de referencia de Bash para obtener todos los detalles sangrientos.
Todd A. Jacobs el

1
Esto no tiene nada que ver con la desreferenciación sino interpolar y exprse desaconseja en 2013.
Gilles Quenot

@sputnick Estás claramente confundido. Por favor, siéntase libre de consultar un diccionario. Ver desreferenciar e interpolar .
Todd A. Jacobs el

1
Una palabra mejor se está expandiendo , pero no eliminando referencias . la desreferenciación se usa cuando usamos punteros , ese no es el caso aquí, solo son variables simples.
Gilles Quenot

1
@Prashant: no se sabe que tldp sea una buena referencia en el mundo bash.
Gilles Quenot

1

Supongamos

x=50
y=5

luego

z=$((x/y))

Esto funcionará correctamente. Pero si desea usar / operator en las declaraciones de caso, entonces no puede resolverlo. Ingresa el código aquí En ese caso, use cadenas simples como div o devide u otra cosa. Ver el código


Esto está mal. /funciona bien como una etiqueta de carcasa. Lo que no funciona es usarlo *para multiplicar sin citarlo, que podría ser lo que realmente hiciste; eso hace que anule efectivamente todos los elementos siguientes en el caso, que en su ejemplo es 'devide' y 'modulo'
dave_thompson_085

0

Para obtener los números después del punto decimal, puede hacer esto: -

read num1 num2
div=`echo $num1 / $num2 |bc -l`
echo $div
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.