Eine klare Antwort wurde bereits von @charles Dufy und anderen gegeben. Eine reine Bash-Lösung würde Folgendes verwenden:
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 zu haben .
Um die schwebenden Zahlen und die wissenschaftliche Notation gründlicher zu unterstützen (viele Programme in C / Fortran oder 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 Möglichkeit, Zahlentypen zu unterscheiden, 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
Hinweis: Wir könnten die syntaktischen Anforderungen für die Dezimal- und wissenschaftliche Notation auflisten. Eine davon besteht darin, Komma als Radixpunkt sowie "." Zuzulassen. Wir würden dann behaupten, dass es nur einen solchen Radixpunkt geben muss. In einem [Ee] -Float können zwei +/- Zeichen stehen. Ich habe ein paar weitere Regeln aus Aulus Arbeit gelernt und gegen schlechte Saiten wie '' '-' '-E-1' '0-0' getestet. Hier sind meine Regex / Teilzeichenfolge / Ausdruck-Tools, die anscheinend halten:
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
test && echo "foo" && exit 0 || echo "bar" && exit 1
Ihnen verwendete Ansatz kann einige unbeabsichtigte Nebenwirkungen haben - wird das Echoexit 0
übersprungen (möglicherweise wird es an einen geschlossenen FD ausgegeben), das wird übersprungen, und der Code versucht es dannecho "bar"
. Wenn dies auch fehlschlägt, schlägt die&&
Bedingung fehl und wird nicht einmal ausgeführtexit 1
! Die Verwendung tatsächlicherif
Aussagen anstelle von&&
/||
ist weniger anfällig für unerwartete Nebenwirkungen.