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:
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:
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))
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.1232>/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'1e102>/dev/null
$ printf '%d\n'"$int"1
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:
==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.
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
printf "1 + %s\n" $1 won't do ?
Antworten:
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:oder allgemein bevorzugt:
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
:Oder Sie können eine Shell mit Gleitkomma-Unterstützung anstelle von bash verwenden:
quelle
Auf andere Weise können Sie verwenden
expr
Ex:
quelle
In
bash
können Sie die Konvertierung von irgendetwas in eine Ganzzahl mit printf -v durchführen :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:
quelle
printf -v
kann dies durch Befehlsersetzung erreicht werden:int="$(printf '%d' 123.123 2>/dev/null)"
bash
hast du benutzt?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:Die Lösung bestand darin, das Ergebnis in eine Ganzzahl umzuwandeln, ähnlich der Antwort von @ John1024, damit es wie erwartet funktioniert:
quelle
==
etc in[[
(auch[
akatest
) 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.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.quelle
$((var+var))
Fail Even (Selbst fehlschlagen) Wenn Sieecho
oderprintf
beide 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 sovar='0'
var=0
sed
wenn Sie sie nicht deaktivieren können