Eine klare Antwort wurde bereits von @charles Dufy und anderen gegeben. Eine reine Bash-Lösung wäre die Verwendung der folgenden :
string="-12,345"
if [[ "$string" =~ ^-?[0-9]+[.,]?[0-9]*$ ]]
then
echo $string is a number
else
echo $string is not a number
fi
Obwohl es für reelle Zahlen nicht zwingend erforderlich ist, eine Zahl vor dem Radixpunkt .
Um eine gründlichere Unterstützung von Fließkommazahlen und wissenschaftlicher Notation zu bieten (viele Programme in C/Fortran oder anderen Sprachen exportieren float auf diese Weise), wäre eine nützliche Ergänzung zu dieser Zeile die folgende:
string="1.2345E-67"
if [[ "$string" =~ ^-?[0-9]*[.,]?[0-9]*[eE]?-?[0-9]+$ ]]
then
echo $string is a number
else
echo $string is not a number
fi
Dies führt zu einer Unterscheidung der Zahlentypen, wenn Sie nach einem bestimmten Typ suchen:
string="-12,345"
if [[ "$string" =~ ^-?[0-9]+$ ]]
then
echo $string is an integer
elif [[ "$string" =~ ^-?[0-9]*[.,]?[0-9]*$ ]]
then
echo $string is a float
elif [[ "$string" =~ ^-?[0-9]*[.,]?[0-9]*[eE]-?[0-9]+$ ]]
then
echo $string is a scientific number
else
echo $string is not a number
fi
Anmerkung: Wir könnten die syntaktischen Anforderungen für die dezimale und die wissenschaftliche Notation auflisten, wobei eine davon darin besteht, das Komma als Radixpunkt zuzulassen, ebenso wie das ".". Wir würden dann behaupten, dass es nur einen solchen Radixpunkt geben darf. In einer [Ee]-Fließkommazahl können zwei Vorzeichen vorkommen. Ich habe noch ein paar weitere Regeln aus Aulus Arbeit gelernt und gegen schlechte Zeichenketten wie '' '-' '-E-1' '0-0' getestet. Hier sind meine Regex/Substring/Expr-Tools, die sich zu bewähren scheinen:
parse_num() {
local r=`expr "$1" : '.*\([.,]\)' 2>/dev/null | tr -d '\n'`
nat='^[+-]?[0-9]+[.,]?$' \
dot="${1%[.,]*}${r}${1##*[.,]}" \
float='^[\+\-]?([.,0-9]+[Ee]?[-+]?|)[0-9]+$'
[[ "$1" == $dot ]] && [[ "$1" =~ $float ]] || [[ "$1" =~ $nat ]]
} # usage: parse_num -123.456
21 Stimmen
Nebenbei bemerkt - die
test && echo "foo" && exit 0 || echo "bar" && exit 1
Ansatz, den Sie verwenden, kann einige unbeabsichtigte Nebeneffekte haben -- wenn das Echo fehlschlägt (vielleicht ist die Ausgabe an einen geschlossenen FD), wird dieexit 0
wird übersprungen, und der Code wird dann versuchenecho "bar"
. Scheitert sie auch daran, wird die&&
wird fehlschlagen, und es wird nicht einmal ausgeführtexit 1
! Mit aktuellenif
Erklärungen und nicht&&
/||
ist weniger anfällig für unerwartete Nebenwirkungen.0 Stimmen
@CharlesDuffy Das ist die Art von wirklich cleverem Denken, zu dem die meisten Leute nur kommen, wenn sie haarige Bugs aufspüren müssen...! Ich hätte nie gedacht, dass Echo einen Fehler zurückgeben könnte.
13 Stimmen
Ich bin zwar etwas spät dran, aber ich weiß um die Gefahren, über die Charles geschrieben hat, da ich sie vor einiger Zeit auch durchmachen musste. Hier ist also eine 100 % narrensichere (und gut lesbare) Zeile für Sie:
[[ $1 =~ "^[0-9]+$" ]] && { echo "number"; exit 0; } || { echo "not a number"; exit 1; }
Die geschweiften Klammern zeigen an, dass die Dinge NICHT in einer Subshell ausgeführt werden sollen (was bei()
stattdessen Klammern verwenden). Vorbehalt: Niemals das letzte Semikolon vergessen . Andernfalls könnten Siebash
um die hässlichsten (und sinnlosesten) Fehlermeldungen auszugeben...9 Stimmen
In Ubuntu funktioniert es nicht, es sei denn, Sie entfernen die Anführungszeichen nicht. Es sollte also einfach sein
[[ 12345 =~ ^[0-9]+$ ]] && echo OKKK || echo NOOO
0 Stimmen
...ich habe die (fehlerhafte) Antwort aus der Frage entfernt - Antworten sollten unter anderem deshalb getrennt sein, damit sie einzeln kommentiert, abgestimmt, korrigiert usw. werden können.
8 Stimmen
Sie müssen sein spezifischer was Sie meinen mit "Nummer" . Eine ganze Zahl? Eine Festkommazahl? Wissenschaftliche ("e") Notation? Ist ein bestimmter Bereich vorgeschrieben (z. B. ein 64-Bit-Wert ohne Vorzeichen), oder ist jede Zahl zulässig, die geschrieben werden kann?
0 Stimmen
Es ist unglaublich, dass die Bash keine zuverlässige, eingebaute Möglichkeit bietet, zu überprüfen, ob ein Wert numerisch ist oder nicht. Die Anzahl, die Vielfalt und die unterschiedliche Qualität der Antworten hier zeigen, dass dies ein ernstes Problem ist.
2 Stimmen
Die Bash bietet eine zuverlässige Methode, um festzustellen, ob eine Zahl ein INTEGER ist. { VAR="asdfas" ; (( VAR )) ; echo $?; } Die Gleichung wird korrekt fehlschlagen, wenn die Antwort "0" lautet, da "0" keine ganze Zahl ist. Ich hatte vor ein paar Minuten genau das gleiche Problem und habe diesen Thread mit einer schnellen Suche gefunden. Ich hoffe, das hilft anderen. Andere Leute waren allerdings nah dran.
0 Stimmen
@Der eine Typ aus dem Film Ihr Code gibt hässliche Meldungen auf stderr aus. Zum Beispiel
((5a))
gibtbash: ((: 5a: value too great for base (error token is "5a")