Fare semplici calcoli sulla riga di comando usando le funzioni bash: $ 1 diviso per $ 2 (usando forse bc)


33

A volte ho bisogno di dividere un numero per un altro. Sarebbe bello se potessi definire una funzione bash per questo. Finora, sono costretto a usare espressioni come

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

ma sarebbe fantastico se potessi definire una funzione .bashrc che sembrava

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

Risposte:


45

Ho una pratica funzione bash chiamata calc:

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

Esempio di utilizzo:

$ calc 65320/670
97.49253731343283582089

$ calc 65320*670
43764400

Puoi cambiarlo per adattarlo a te stesso. Per esempio:

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

Nota: <<< è una stringa qui che viene inserita nello stdin di bc. Non è necessario invocare echo.


3
Sono d'accordo che sembra migliore senza l'eco aggiuntiva generata, ma dal momento che è incorporato in una shell, viene fornito con poco o nessun costo aggiuntivo. Ciò che mi impedisce di usare '<<<' nelle funzioni della shell è la sua limitazione a bash, mentre l'eco aggiuntiva consente di usarlo nella shell bourne originale o in ksh senza modifiche.
Tatjana Heuser,

@TatjanaHeuser ksh, la variante 93, supporta le stringhe qui.
Kusalananda

Per assegnare a una variabile, ho fatto questo: foo = $ (bc -l <<< "(2 * 5) + 5")
thebiggestlebowski

20

Bash può fare la matematica stessa in una certa misura. Non è utile per la precisione, tuttavia, poiché arrotonda.

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

Ma hai esattamente ragione: una funzione bash sarebbe una semplice scorciatoia e il tuo esempio sostanzialmente funziona.

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

Buttalo nel tuo .bashrc e poi puoi:

[user]$ divide 10 5
2.0000000000000000000000000

1
echo $((10 / 5))non ha bisogno di preventivi.
utente sconosciuto

1
Disturbo significativo: echo $((6383/7671)) ti darà zero. Devi essere esplicito sui numeri in virgola mobile:echo $((6383.0/7671.0))
Sridhar Sarnobat,

9

Probabilmente conosci il bash builtin 'expr' come in

$ expr 60 / 5
12

che è limitato a numeri interi e necessita degli spazi tra gli argomenti.

Cosa ti impedisce di definire una funzione lungo le linee dell'espressione dell'eco che stai già utilizzando? ie

 divide () {
   echo $1/$2 | bc
 }

1
solo ignoranza. non mi rendevo conto che avrei potuto farlo funzionare in quel modo ...
ixtmixilix,

7

Non è proprio una risposta a questa domanda precisa, ma potrebbe essere utile saperlo. Usa zsh;-)

% echo $((65320./670))
97.492537313432834

In realtà stavo cercando questa domanda perché sono passato a zsh e non ho potuto usare il exprbuilt-in di bash , quindi una buona risposta a prescindere :)
Steen Schütt

2

Se hai calcinstallato sul tuo sistema e non ti piace arrotondare, puoi:

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

hmm ... non ho trovato nessun pacchetto debian per 'calc'
ixtmixilix

Il pacchetto si chiama apcalc (Precisione arbitraria) ... Il binario si chiamacalc
Peter.O

@ Peter.O Ok, si chiama nei repository Arch Linux calc.

2

Un trucco sporco per piccoli valori e una precisione limitata senza usare bc sarebbe, per moltiplicare il nominatore prima della divisione, per ottenere un risultato accurato.

Esempio senza precisione:

echo $((13/7)) 
1

e con precisione a 2 cifre: moltiplicare per 100 e spostare il punto decimale di 2 passi verso sinistra:

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

Ciò è utile solo se l'intervallo di numeri è già noto e la precisione è sempre la stessa. Evitare di chiamare bc e chiamare sed non sembra molto ragionevole.

Si noti che la moltiplicazione dei valori potrebbe causare errori di overflow, ma non molto presto:

echo $((1000000000*12345678901))
-6101065172709551616

L'uso delle doppie parentesi per valutare le espressioni matematiche è deprecato. Usa: $[expression]invece
laebshade,

3
@laebshade: posso provare che ti sbagli, è vero il contrario. Ecco una citazione del manuale di bash:The old format $[expression] is deprecated and will be removed in upcoming versions of bash.
utente sconosciuto

Discusso anche qui ,  qui  e  qui .
G-Man dice "Reinstate Monica" il

0

Invece di usare bc, puoi usare awk:

div() { awk -v p=$1 -v q=$2 'BEGIN{print p/q}'; }

-4
echo Division
efgh=$num1/$num2
remainder=$num1%num2
echo $num1 "/" $num2 "=" $efgh.$remainder
echo
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.