Haciendo cálculos matemáticos simples en la línea de comando usando funciones bash: $ 1 dividido por $ 2 (usando bc quizás)

33

A veces necesito dividir un número por otro. Sería genial si pudiera definir una función bash para esto. Hasta ahora, me veo obligado a usar expresiones como

echo 'scale=25;65320/670' | bc

pero sería genial si pudiera definir una función .bashrc que se pareciera a

divide () {
  bc -d $1 / $2
}
ixtmixilix
fuente

Respuestas:

45

Tengo una práctica función bash llamada calc:

calc () {
    bc -l <<< "$@"
}

Ejemplo de uso:

$ calc 65320/670
97.49253731343283582089

$ calc 65320*670
43764400

Puede cambiar esto para adaptarse a usted mismo. Por ejemplo:

divide() {
    bc -l <<< "$1/$2"
}

Nota: <<< es una cadena aquí que se alimenta al stdin de bc. No necesitas invocar echo.

dogbane
fuente
3
Estoy de acuerdo en que se ve mejor sin el eco adicional incluido, pero como se trata de una carcasa incorporada, tiene poco o ningún costo adicional. Lo que me impide usar '<<<' en las funciones de shell es su limitación a bash, mientras que el eco adicional permite usarlo en el shell bourne original o ksh sin cambios.
Tatjana Heuser
@TatjanaHeuser ksh, la variante 93, admite cadenas aquí.
Kusalananda
Para asignar a una variable, hice esto: foo = $ (bc -l <<< "(2 * 5) + 5")
thebiggestlebowski
20

Bash puede hacer los cálculos en sí mismo hasta cierto punto. Sin embargo, no es útil para la precisión, ya que se redondea.

[user]$ echo $(( 10/5 ))
2

Pero tiene toda la razón: una función bash sería un acceso directo simple y su ejemplo básicamente funciona.

divide() {
  echo "scale=25;$1/$2" | bc
}

Tíralo en tu .bashrc y luego podrás:

[user]$ divide 10 5
2.0000000000000000000000000
rjewell
fuente
1
echo $((10 / 5))No necesita presupuesto.
usuario desconocido
1
Molestia significativa: echo $((6383/7671)) te dará cero. echo $((6383.0/7671.0))
Debe
9

Probablemente conoces el bash 'expr' incorporado como en

$ expr 60 / 5
12

que se limita a enteros y necesita los espacios entre los argumentos.

¿Qué le impide definir una función a lo largo de las líneas de la expresión de eco que ya está utilizando? Es decir

 divide () {
   echo $1/$2 | bc
 }
Tatjana Heuser
fuente
1
solo ignorancia. No me di cuenta que podría hacer que funcione de esa manera ...
ixtmixilix
7

Realmente no es una respuesta a esta pregunta precisa, pero podría ser bueno saberlo. Uso zsh;-)

% echo $((65320./670))
97.492537313432834
Stéphane Gimenez
fuente
En realidad estaba buscando esta pregunta porque he cambiado a zsh y no podía usar de fiesta exprorden interna, por lo que buena respuesta independientemente :)
Steen Schütt
2

Si ha calcinstalado en su sistema y no le gusta redondear, puede:

div() { calc "$1 / $2"; }

fuente
hmm ... no pude encontrar ningún paquete debian para 'calc'
ixtmixilix
El paquete se llama apcalc (Arbitary Precision) ... El binario se llamacalc
Peter.O
@ Peter.O Ok, en los repositorios de Arch Linux se llama calc.
2

Un truco sucio para valores pequeños y una precisión limitada sin usar bc sería, para multiplicar el nominador antes de la división, para obtener un resultado preciso.

Ejemplo sin precisión:

echo $((13/7)) 
1

y con precisión de 2 dígitos: multiplique por 100 y mueva el punto decimal 2 pasos hacia la izquierda:

echo $((100*13/7)) | sed 's/..$/.&/'
1.85
echo $((100*13/7))%
185%

Esto solo es útil si el rango de números se conoce antes, y la precisión es siempre la misma. Evitar llamar a bc y llamar a sed no parece muy razonable.

Tenga en cuenta que multiplicar los valores puede provocar errores de desbordamiento, pero no muy pronto:

echo $((1000000000*12345678901))
-6101065172709551616
usuario desconocido
fuente
El uso de paréntesis dobles para evaluar expresiones matemáticas está en desuso. Uso: en su $[expression]lugar
sombra de ojos
3
@laebshade: Puedo demostrar que te equivocas, lo contrario es cierto. Aquí hay una cita del manual de bash:The old format $[expression] is deprecated and will be removed in upcoming versions of bash.
usuario desconocido
También discutido aquí ,  aquí  y  aquí .
G-Man dice 'Restablecer a Monica' el
0

En lugar de usar bc, puedes usar awk:

div() { awk -v p=$1 -v q=$2 'BEGIN{print p/q}'; }
jfg956
fuente
-4
echo Division
efgh=$num1/$num2
remainder=$num1%num2
echo $num1 "/" $num2 "=" $efgh.$remainder
echo
Boomer
fuente