Argumentstring zu Integer in Bash

74

Versuchen Sie herauszufinden, wie Sie ein Argument in eine Ganzzahl konvertieren, um eine Arithmetik auszuführen, und drucken Sie es dann aus, beispielsweise für addOne.sh:

echo $1 + 1
>>sh addOne.sh 1
prints 1 + 1
user135986
quelle
Ich versuche Ihre Frage zu formatieren, aber es bleibt irgendwie unklar. printf "1 + %s\n" $1 won't do ?
Archemar

Antworten:

88

In der Bash konvertiert man kein Argument in eine Ganzzahl, um eine Arithmetik durchzuführen. In der Bash werden Variablen je nach Kontext als Ganzzahl oder Zeichenfolge behandelt.

Um Arithmetik auszuführen, sollten Sie den arithmetischen Expansionsoperator aufrufen $((...)). Zum Beispiel:

$ a=2
$ echo "$a + 1"
2 + 1
$ echo "$(($a + 1))"
3

oder allgemein bevorzugt:

$ echo "$((a + 1))"
3

Sie sollten sich bewusst sein, dass bash (im Gegensatz zu ksh93, zsh oder yash) nur Ganzzahlarithmetik ausführt . Wenn Sie Gleitkommazahlen (Zahlen mit Dezimalstellen) haben, gibt es andere Hilfsmittel. Verwenden Sie zum Beispiel bc:

$ b=3.14
$ echo "$(($b + 1))"
bash: 3.14 + 1: syntax error: invalid arithmetic operator (error token is ".14 + 1")
$ echo "$b + 1" | bc -l
4.14

Oder Sie können eine Shell mit Gleitkomma-Unterstützung anstelle von bash verwenden:

zsh> echo $((3.14 + 1))
4.14
John1024
quelle
Die Verwendung von $ (()) oder (()) ist unsicher, wenn Sie die Zeichenfolgen nicht kennen (z. B. Benutzereingaben). Betrachten Sie Folgendes: foo = foo ((foo + = 0)) Dies wird das Skript zum Absturz bringen, wenn es versucht, foo rekursiv auszuwerten. Gleiches gilt für: foo = foo foo = $ ((foo + 0))
Art
12

Auf andere Weise können Sie verwenden expr

Ex:

$ version="0002"
$ expr $version + 0
2
$ expr $version + 1
3
Nam
quelle
10

In bashkönnen Sie die Konvertierung von irgendetwas in eine Ganzzahl mit printf -v durchführen :

printf -v int '%d\n' "$1" 2>/dev/null

Gleitende Zahlen werden in Ganzzahlen umgewandelt, während alles, was nicht wie eine Zahl aussieht, in 0 umgewandelt wird. Die Potenzierung wird auf die vorhergehende Zahl abgeschnitten e

Beispiel:

$ printf -v int '%d\n' 123.123 2>/dev/null
$ printf '%d\n' "$int"
123
$ printf -v int '%d\n' abc 2>/dev/null
$ printf '%d\n' "$int"
0
$ printf -v int '%d\n' 1e10 2>/dev/null
$ printf '%d\n' "$int"
1
cuonglm
quelle
2
In anderen Shells ohne printf -vkann dies durch Befehlsersetzung erreicht werden:int="$(printf '%d' 123.123 2>/dev/null)"
Adrian Günter
2
Dies funktioniert nicht in Bash.
Michael Martinez
@MichaelMartinez bist du sicher? Welche Version bashhast du benutzt?
Donnerstag,
GNU bash, version 4.2.46 (1) -release (x86_64-redhat-linux-gnu)
Michael Martinez
5

Eine ähnliche Situation ergab sich kürzlich bei der Entwicklung von Bash-Skripten für Linux- und OSX-Umgebungen. Das Ergebnis eines Befehls in OSX gab eine Zeichenfolge mit dem Ergebniscode zurück. dh " 0". In folgendem Fall konnte dies natürlich nicht richtig getestet werden:

if [[ $targetCnt != 0 ]]; then...

Die Lösung bestand darin, das Ergebnis in eine Ganzzahl umzuwandeln, ähnlich der Antwort von @ John1024, damit es wie erwartet funktioniert:

targetCnt=$(($targetCnt + 0))
if [[ $targetCnt != 0 ]]; then...
JESii
quelle
3
==etc in [[(auch [aka test) tun Stringvergleich. Es gibt verschiedene Operatoren für den arithmetischen Vergleich, z [[ $targetcnt -ne 0 ]]. Siehe Hilfeseite (oder Info) unter Bedingte Ausdrücke. Um Leerzeichen spezifisch zu trimmen, können Sie [mit der nicht [ $targetcnt == 0 ]zitierten Variablenerweiterung die Standard-Worttrennung (NICHT in [[) verwenden, aber im Allgemeinen führt Sie dieser Ansatz in Gefahr.
Dave_thompson_085
-2

Wenn Sie sich um Farbcodes kümmern, selbst wenn trace ( -x) nicht angezeigt wird, wird die Zeichenfolge, die eine Zahl sein soll, in Anführungszeichen gesetzt, unabhängig davon, wie Sie sie drucken.

untore
quelle
1
Abgestimmt, da ich Ihre Antwort etwas unklar finde. Vielleicht könnten Sie hinzufügen, worauf das Skript korrigiert werden sollte?
Time4Tea
Dies war die häufigste Antwort bei der Suche nach Bash + Integer + String. Daher habe ich eine Information hinzugefügt, die nicht in den Antworten enthalten war. Wenn also Strings in Farbcodes eingebunden sind, ist möglicherweise nicht klar, warum Operationen wie $((var+var))Fail Even (Selbst fehlschlagen) Wenn Sie echooder printfbeide Vars gleich sind. Ich kenne das Update nicht, da ich es nur durch Deaktivieren der Farbcodes an der Quelle der Ausgabe beheben konnte. Um es in den Ablaufverfolgungsprotokollen zu erkennen, wird die beleidigende Variable so var='0'var=0
angezeigt,
Stellen Sie sicher, dass die Ausgabe keine Farbcodes enthält, sedwenn Sie sie nicht deaktivieren können
2.