Jasna odpowiedź została już udzielona przez @charles Dufy i innych. Rozwiązaniem czysto bashowym byłoby użycie:
string="-12,345"
if [[ "$string" =~ ^-?[0-9]+[.,]?[0-9]*$ ]]
then
echo $string is a number
else
echo $string is not a number
fi
Chociaż w przypadku liczb rzeczywistych nie jest obowiązkowe, aby mieć liczbę przed punktem bazowym .
Aby zapewnić dokładniejszą obsługę liczb zmiennoprzecinkowych i notacji naukowej (wiele programów w C / Fortran lub w inny sposób eksportuje liczby zmiennoprzecinkowe w ten sposób), przydatnym dodatkiem do tego wiersza byłoby:
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
Prowadząc w ten sposób do rozróżnienia typów liczb, jeśli szukasz jakiegoś konkretnego typu:
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
Uwaga: Moglibyśmy wymienić wymagania syntaktyczne dla notacji dziesiętnej i naukowej, przy czym jednym z nich jest zezwolenie na przecinek jako punkt radix, a także „.”. Twierdzilibyśmy wtedy, że musi istnieć tylko jeden taki punkt bazowy. Mogą występować dwa znaki +/- w pływaka [Ee]. Nauczyłem się jeszcze kilku zasad z pracy Aulu i przetestowałem na złych ciągach, takich jak „” - „” -E-1 ”„ 0-0 ”. Oto moje narzędzia regex / substring / expr, które wydają się wstrzymywać:
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
podejście może mieć pewne niezamierzone skutki uboczne - jeśli echo się nie powiedzie (być może sygnał wyjściowy jest do zamkniętego FD),exit 0
zostanie ono pominięte, a kod spróbuje to zrobićecho "bar"
. Jeśli to też zawiedzie,&&
warunek się nie powiedzie i nawet się nie wykonaexit 1
! Używanie rzeczywistychif
instrukcji zamiast&&
/||
jest mniej podatne na nieoczekiwane skutki uboczne.