Einfache Mathematik in der Befehlszeile mit Bash-Funktionen ausführen: $ 1 geteilt durch $ 2 (mit bc vielleicht)


33

Manchmal muss ich eine Zahl durch eine andere teilen. Es wäre großartig, wenn ich dafür einfach eine Bash-Funktion definieren könnte. Bisher bin ich gezwungen, Ausdrücke wie zu verwenden

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

Aber es wäre großartig, wenn ich eine .bashrc-Funktion definieren könnte, die so aussieht

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

Antworten:


45

Ich habe eine praktische Bash-Funktion namens calc:

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

Anwendungsbeispiel:

$ calc 65320/670
97.49253731343283582089

$ calc 65320*670
43764400

Sie können dies nach Ihren Wünschen ändern. Beispielsweise:

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

Hinweis: <<< Ist eine Here-Zeichenfolge, die in das STDIN von eingegeben wird bc. Sie müssen nicht aufrufen echo.


3
Ich bin damit einverstanden, dass es ohne das zusätzliche Echo besser aussieht, aber da es sich um eine eingebaute Shell handelt, fallen nur geringe oder keine zusätzlichen Kosten an. Was mich davon abhält, '<<<' in Shell-Funktionen zu verwenden, ist die Beschränkung auf bash, während das zusätzliche Echo es ermöglicht, es in der ursprünglichen Borowski-Shell oder in ksh ohne Änderungen zu verwenden.
Tatjana Heuser

@TatjanaHeuser ksh, die 93-Variante, unterstützt Here-Strings.
Kusalananda

Um eine Variable zuzuweisen, habe ich
Folgendes

20

Bash kann bis zu einem gewissen Grad selbst rechnen. Es ist jedoch nicht nützlich für die Genauigkeit, da es rundet.

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

Aber Sie haben genau Recht - eine Bash-Funktion wäre eine einfache Abkürzung und Ihr Beispiel funktioniert im Grunde.

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

Werfen Sie das in Ihre .bashrc und dann können Sie:

[user]$ divide 10 5
2.0000000000000000000000000

1
echo $((10 / 5))braucht kein Zitat.
Benutzer unbekannt

1
Erhebliche Belästigung: echo $((6383/7671)) Sie erhalten null. Sie müssen explizit über Gleitkommazahlen sein:echo $((6383.0/7671.0))
Sridhar Sarnobat

9

Sie kennen wahrscheinlich die Bash-Funktion "expr" wie in

$ expr 60 / 5
12

Das ist auf ganze Zahlen beschränkt und benötigt die Leerzeichen zwischen den Argumenten.

Was hindert Sie daran, eine Funktion in Anlehnung an den Echoausdruck zu definieren, den Sie bereits verwenden? Dh

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

1
nur Unwissenheit. Ich wusste nicht, dass ich es so machen könnte ...
ixtmixilix

7

Keine wirkliche Antwort auf diese genaue Frage, aber es könnte gut sein, sie zu kennen. Benutze zsh;-)

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

Ich habe nach dieser Frage gesucht, weil ich zu zsh gewechselt bin und Bashs exprBuiltin nicht verwenden konnte, also trotzdem eine gute Antwort :)
Steen Schütt

2

Wenn Sie calcauf Ihrem System installiert haben und das Runden nicht mögen, können Sie:

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

hmm ... konnte kein Debian-Paket für 'calc'
ixtmixilix am

Das Paket heißt apcalc (Arbitary Precision) ... Die Binärdatei heißtcalc
Peter.O

@ Peter.O Ok, in den Arch Linux-Repos heißt es calc.

2

Ein schmutziger Hack für kleine Werte und eine begrenzte Genauigkeit ohne Verwendung von bc wäre, den Nominator vor der Division zu multiplizieren, um ein genaues Ergebnis zu erhalten.

Beispiel ohne Genauigkeit:

echo $((13/7)) 
1

und mit 2-stelliger Genauigkeit: Mit 100 multiplizieren und den Dezimalpunkt 2 Schritte nach links verschieben:

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

Dies ist nur sinnvoll, wenn der Zahlenbereich bereits bekannt ist und die Genauigkeit immer gleich ist. Zu vermeiden, bc anzurufen , und sed anzurufen , scheint nicht sehr vernünftig zu sein.

Beachten Sie, dass das Multiplizieren der Werte zu Überlauffehlern führen kann, jedoch nicht sehr früh:

echo $((1000000000*12345678901))
-6101065172709551616

Das Auswerten von mathematischen Ausdrücken in doppelten Klammern ist veraltet. Verwenden Sie: $[expression]stattdessen
Laebshade

3
@laebshade: Ich kann dir das Gegenteil beweisen. Hier ist ein Zitat aus dem Bash-Handbuch:The old format $[expression] is deprecated and will be removed in upcoming versions of bash.
Benutzer unbekannt

Auch hier ,  hier  und  hier diskutiert .
G-Man sagt, dass Monica

0

Anstelle von bc können Sie auch awk verwenden:

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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.