Jak sprawdzić, czy zmienna jest liczbą w Bash?

Po prostu nie mogę dowiedzieć się, jak upewnić się, że argument przekazany do mojego skryptu jest liczbą, czy nie.

Chcę tylko zrobić coś takiego:

test *isnumber* $1 && VAR=$1 || echo "need a number"
Jakaś pomoc?
Author: codeforester, 2009-04-30

30 answers

Jednym z sposobów jest użycie wyrażenia regularnego, w ten sposób:

re='^[0-9]+$'
if ! [[ $yournumber =~ $re ]] ; then
   echo "error: Not a number" >&2; exit 1
fi

Jeśli wartość nie musi być liczbą całkowitą, rozważ poprawienie wyrażenia regularnego odpowiednio; na przykład:

^[0-9]+([.][0-9]+)?$

...lub, aby obsłużyć liczby ze znakiem:

^[+-]?[0-9]+([.][0-9]+)?$
 609
Author: Charles Duffy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-26 00:40:36

Bez bashismów (działa nawet w systemie V sh),

case $string in
    ''|*[!0-9]*) echo bad ;;
    *) echo good ;;
esac

To odrzuca puste ciągi i ciągi zawierające niecyfrowe, akceptując Wszystko inne.

Liczby ujemne lub zmiennoprzecinkowe wymagają dodatkowej pracy. Pomysłem jest wykluczenie - / . w pierwszym" złym "wzorze i dodać więcej" złych " wzorców zawierających niewłaściwe ich użycie (?*-* / *.*.*)

 217
Author: jilles,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-10-16 22:56:11

Poniższe rozwiązanie może być również używane w powłokach podstawowych, takich jak Bourne, bez potrzeby stosowania wyrażeń regularnych. Zasadniczo wszelkie operacje oceny wartości liczbowych przy użyciu liczb innych niż liczby spowodują błąd, który będzie domyślnie uważany za false w powłoce:

"$var" -eq "$var"

Jak w:

#!/bin/bash

var=a

if [ -n "$var" ] && [ "$var" -eq "$var" ] 2>/dev/null; then
  echo number
else
  echo not a number
fi

Możesz też przetestować za $? kod powrotu operacji, który jest bardziej wyraźny:

[ -n "$var" ] && ["$var" -eq "$var"] 2>/dev/null
if [ $? -ne 0 ]; then
   echo $var is not number
fi

Przekierowanie błędu standardowego jest tam, aby ukryć " oczekiwane wyrażenie integer" wiadomość, że bash drukuje się na wypadek, gdybyśmy nie mieli numeru.

Zastrzeżenia (dzięki komentarzom poniżej):

  • liczby z punktami dziesiętnymi są Nie identyfikowane jako ważne "liczby"
  • Użycie [[ ]] zamiast [ ] będzie zawsze oceniać na true
  • Większość powłok innych niż Bash zawsze będzie oceniać to wyrażenie jako true
  • zachowanie w Bash jest nieudokumentowane i dlatego może ulec zmianie bez ostrzeżenia
  • Jeśli wartość zawiera spacje po liczbie (np." 1 a") generuje błąd, np. bash: [[: 1 a: syntax error in expression (error token is "a")
  • jeśli wartość jest taka sama jak var-name (np.]}
 148
Author: Alberto Zaccagni,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-04 07:41:25

Testuje, czy liczba jest nieujemną liczbą całkowitą i jest niezależna od powłoki (tzn. bez bashismów) i używa tylko wbudowanych powłok:

[ -z "${num##[0-9]*}" ] && echo "is a number" || echo "is not a number";

ALE JEST ŹLE .
Jak jilles skomentował i zasugerował w swoją odpowiedź jest to prawidłowy sposób, aby to zrobić za pomocą wzorców powłoki.

[ ! -z "${num##*[!0-9]*}" ] && echo "is a number" || echo "is not a number";
 32
Author: mrucci,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:47:30

Jestem zaskoczony rozwiązaniami bezpośrednio parsującymi formaty liczb w powłoce. shell nie nadaje się do tego, będąc DSL do kontrolowania plików i procesów. Istnieje wiele parserów liczb trochę niżej, na przykład:

isdecimal() {
  # filter octal/hex/ord()
  num=$(printf '%s' "$1" | sed "s/^0*\([1-9]\)/\1/; s/'/^/")

  test "$num" && printf '%f' "$num" >/dev/null 2>&1
}

Zmień '% f ' na dowolny wymagany format.

 27
Author: pixelbeat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-15 12:37:08

Nikt nie zasugerował rozszerzonego dopasowania wzorca :

[[ $1 == ?(-)+([0-9]) ]] && echo "$1 is an integer"
 25
Author: glenn jackman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-13 19:49:44

Patrzyłem na odpowiedzi i... zdałem sobie sprawę, że nikt nie myślał o numerach FLOAT (z kropką)!

Używanie grepa też jest świetne.
-E oznacza rozszerzone Wyrażenie regularne
-q oznacza ciche (nie echo)
- qE jest połączeniem obu.

Aby przetestować bezpośrednio w wierszu poleceń:

$ echo "32" | grep -E ^\-?[0-9]?\.?[0-9]+$  
# answer is: 32

$ echo "3a2" | grep -E ^\-?[0-9]?\.?[0-9]+$  
# answer is empty (false)

$ echo ".5" | grep -E ^\-?[0-9]?\.?[0-9]+$  
# answer .5

$ echo "3.2" | grep -E ^\-?[0-9]?\.?[0-9]+$  
# answer is 3.2

Użycie w skrypcie bash:

check=`echo "$1" | grep -E ^\-?[0-9]*\.?[0-9]+$`

if [ "$check" != '' ]; then    
  # it IS numeric
  echo "Yeap!"
else
  # it is NOT numeric.
  echo "nooop"
fi

Aby dopasować tylko liczby całkowite, użyj tego:

# change check line to:
check=`echo "$1" | grep -E ^\-?[0-9]+$`
 13
Author: Sergio Abreu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-20 02:30:28

[[2]}po prostu kontynuacja @ mary. Ale ponieważ nie mam wystarczająco dużo reputacji, nie mogę zamieścić tego jako komentarz do tego posta. Tak czy inaczej, oto czego użyłem:

isnum() { awk -v a="$1" 'BEGIN {print (a == a + 0)}'; }

Funkcja zwróci "1", jeśli argument jest liczbą, w przeciwnym razie zwróci "0". Działa to zarówno dla liczb całkowitych, jak i pływaków. Użycie jest jak:

n=-2.05e+07
res=`isnum "$n"`
if [ "$res" == "1" ]; then
     echo "$n is a number"
else
     echo "$n is not a number"
fi
 11
Author: triple_r,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-13 21:11:22

Http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_04_03.html

Możesz także użyć klas postaci Basha.

if [[ $VAR = *[[:digit:]]* ]]; then
 echo "$VAR is numeric"
else
 echo "$VAR is not numeric"
fi

Liczby będą zawierać spację, punkt dziesiętny i" e "lub" E " Dla zmiennoprzecinkowych.

Ale jeśli podasz liczbę szesnastkową w stylu C, np. "0xffff" lub "0xFFFF", [[: digit:]] zwraca true. Trochę pułapki tutaj, bash pozwala zrobić coś takiego jak "0xAZ00" i nadal liczyć go jako cyfrę (czy to nie z jakiegoś dziwnego dziwactwa kompilatorów GCC, które pozwalają używasz notacji 0x dla baz innych niż 16???)

Przed testowaniem możesz sprawdzić ,czy jest to liczba, Jeśli dane wejściowe są całkowicie niezaufane, chyba że chcesz zaakceptować liczby szesnastkowe. Można by to osiągnąć poprzez:

if [[ ${VARIABLE:1:2} = "0x" ]] || [[ ${VARIABLE:1:2} = "0X" ]]; then echo "$VAR is not numeric"; fi
 7
Author: ultrasawblade,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-12 14:52:19

Stare pytanie, ale chciałem tylko sprawdzić moje rozwiązanie. Ten nie wymaga żadnych dziwnych sztuczek łuskowych ani polegania na czymś, czego nie było od zawsze.

if [ -n "$(printf '%s\n' "$var" | sed 's/[0-9]//g')" ]; then
    echo 'is not numeric'
else
    echo 'is numeric'
fi

Zasadniczo usuwa wszystkie cyfry z wejścia, a jeśli zostanie Ci niezerowy ciąg znaków, to nie była to liczba.

 6
Author: Sammitch,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-13 21:44:37

Spróbowałbym tego:

printf "%g" "$var" &> /dev/null
if [[ $? == 0 ]] ; then
    echo "$var is a number."
else
    echo "$var is not a number."
fi

Uwaga: rozpoznaje nan i inf jako liczbę.

 5
Author: overflowed,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-08 22:43:41

Nie mogę jeszcze skomentować, więc dodam własną odpowiedź, która jest rozszerzeniem odpowiedzi Glenna Jackmana za pomocą dopasowania wzorca Basha.

Moją pierwotną potrzebą było zidentyfikowanie liczb i rozróżnienie liczb całkowitych i pływaków. Definicje funkcji odjęte do:
function isInteger() {
    [[ ${1} == ?(-)+([0-9]) ]]
}

function isFloat() {
    [[ ${1} == ?(-)@(+([0-9]).*([0-9])|*([0-9]).+([0-9]))?(E?(-|+)+([0-9])) ]]
}

Użyłem testów jednostkowych (z shUnit2), aby zweryfikować moje wzorce działały zgodnie z przeznaczeniem:

oneTimeSetUp() {
    int_values="0 123 -0 -123"
    float_values="0.0 0. .0 -0.0 -0. -.0 \
        123.456 123. .456 -123.456 -123. -.456
        123.456E08 123.E08 .456E08 -123.456E08 -123.E08 -.456E08 \
        123.456E+08 123.E+08 .456E+08 -123.456E+08 -123.E+08 -.456E+08 \
        123.456E-08 123.E-08 .456E-08 -123.456E-08 -123.E-08 -.456E-08"
}

testIsIntegerIsFloat() {
    local value
    for value in ${int_values}
    do
        assertTrue "${value} should be tested as integer" "isInteger ${value}"
        assertFalse "${value} should not be tested as float" "isFloat ${value}"
    done

    for value in ${float_values}
    do
        assertTrue "${value} should be tested as float" "isFloat ${value}"
        assertFalse "${value} should not be tested as integer" "isInteger ${value}"
    done

}

Uwagi: wzorzec isFloat można zmodyfikować tak, aby był bardziej tolerancyjny względem punktu dziesiętnego (@(.,)) i symbolu E (@(Ee)). Moja jednostka testy testują tylko wartości, które są liczbą całkowitą lub zmiennoprzecinkową, ale nie niepoprawne dane wejściowe.

 5
Author: karttu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-24 13:59:53
[[ $1 =~ ^-?[0-9]+$ ]] && echo "number"

Nie zapomnij - dodać liczby ujemne!

 4
Author: D_I,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-12 05:15:14

Używam expr. Zwraca niezerową wartość, jeśli spróbujesz dodać zero do wartości nieliczbowej:

if expr $number + 0 > /dev/null 2>&1
then
    echo "$number is a number"
else
    echo "$number isn't a number"
fi

Może być możliwe użycie bc jeśli potrzebujesz Nie-liczb całkowitych, ale nie wierzę, że bc ma takie samo zachowanie. Dodanie zera do liczby niezerowej daje zero i zwraca również wartość zero. Może uda Ci się połączyć bc i expr. Użyj bc, aby dodać zero do $number. Jeśli odpowiedź brzmi 0, spróbuj expr sprawdzić, czy $number nie jest zerem.

 3
Author: David W.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-27 03:45:01
test -z "${i//[0-9]}" && echo digits || echo no no no

${i//[0-9]} zastępuje dowolną cyfrę w wartości $i pustym łańcuchem, patrz man -P 'less +/parameter\/' bash. -z sprawdza, czy wynikowy łańcuch ma zerową długość.

Jeśli chcesz również wykluczyć przypadek, gdy $i jest pusty, możesz użyć jednej z tych konstrukcji:

test -n "$i" && test -z "${i//[0-9]}" && echo digits || echo not a number
[[ -n "$i" && -z "${i//[0-9]}" ]] && echo digits || echo not a number
 3
Author: user2683246,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-05 16:46:24

Najprostszym sposobem jest sprawdzenie, czy zawiera znaki niecyfrowe. Zamieniasz wszystkie znaki cyfr na nic i sprawdzasz długość. Jeśli jest długość to nie jest liczba.

if [[ ! -n ${input//[0-9]/} ]]; then
    echo "Input Is A Number"
fi
 3
Author: Andrew Anthony Gerst,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-27 17:21:51

Jasną odpowiedź udzielili już @ charles Dufy i inni. Czyste rozwiązanie bash byłoby za pomocą następujących :

string="-12,345"
if [[ "$string" =~ ^-?[0-9]+[.,]?[0-9]*$ ]]
then
    echo $string is a number
else
    echo $string is not a number
fi

Chociaż dla liczb rzeczywistych nie jest obowiązkowe posiadanie liczby przed punktem radix .

Aby zapewnić dokładniejsze wsparcie dla liczb zmiennoprzecinkowych i notacji naukowej (wiele programów w C / Fortran lub w inny sposób eksportuje float w ten sposób), użytecznym dodatkiem do tej linii będzie:

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

W ten sposób prowadzi do rozróżnij typy 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: możemy wymienić wymagania składniowe dla notacji dziesiętnej i naukowej, jednym z nich jest dopuszczenie przecinka jako punktu radix, a także ".". Twierdzimy wtedy, że musi istnieć tylko jeden taki punkt radix. W [EE] float mogą występować dwa znaki+/ -. Z pracy Aulu nauczyłem się jeszcze kilku zasad i przetestowałem na złych strunach takich jak " '-' '- E-1 ''0-0'. Oto moje narzędzia regex / substring/expr to chyba się trzyma:

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
 3
Author: Aulo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-06 08:47:19

[[2]}ponieważ musiałem ostatnio z tym manipulować i jak karttu ' S appoach z testem jednostkowym najbardziej. Poprawiłem kod i dodałem kilka innych rozwiązań, wypróbuj go sam, aby zobaczyć wyniki: {]}

#!/bin/bash

    # N={0,1,2,3,...} by syntaxerror
function isNaturalNumber()
{
 [[ ${1} =~ ^[0-9]+$ ]]
}
    # Z={...,-2,-1,0,1,2,...} by karttu
function isInteger() 
{
 [[ ${1} == ?(-)+([0-9]) ]]
}
    # Q={...,-½,-¼,0.0,¼,½,...} by karttu
function isFloat() 
{
 [[ ${1} == ?(-)@(+([0-9]).*([0-9])|*([0-9]).+([0-9]))?(E?(-|+)+([0-9])) ]]
}
    # R={...,-1,-½,-¼,0.E+n,¼,½,1,...}
function isNumber()
{
 isNaturalNumber $1 || isInteger $1 || isFloat $1
}

bools=("TRUE" "FALSE")
int_values="0 123 -0 -123"
float_values="0.0 0. .0 -0.0 -0. -.0 \
    123.456 123. .456 -123.456 -123. -.456 \
    123.456E08 123.E08 .456E08 -123.456E08 -123.E08 -.456E08 \
    123.456E+08 123.E+08 .456E+08 -123.456E+08 -123.E+08 -.456E+08 \
    123.456E-08 123.E-08 .456E-08 -123.456E-08 -123.E-08 -.456E-08"
false_values="blah meh mooh blah5 67mooh a123bc"

for value in ${int_values} ${float_values} ${false_values}
do
    printf "  %5s=%-30s" $(isNaturalNumber $value) ${bools[$?]} $(printf "isNaturalNumber(%s)" $value)
    printf "%5s=%-24s" $(isInteger $value) ${bools[$?]} $(printf "isInteger(%s)" $value)
    printf "%5s=%-24s" $(isFloat $value) ${bools[$?]} $(printf "isFloat(%s)" $value)
    printf "%5s=%-24s\n" $(isNumber $value) ${bools[$?]} $(printf "isNumber(%s)" $value)
done

Więc isnumber () zawiera myślniki, przecinki i notację wykładniczą i dlatego zwraca TRUE na liczbach całkowitych i pływakach, gdzie z drugiej strony isFloat () zwraca FALSE na wartościach całkowitych iisInteger () podobnie zwraca FALSE na pływakach. Dla Twojej wygody wszystkie jako jedna wkładka:

isNaturalNumber() { [[ ${1} =~ ^[0-9]+$ ]]; }
isInteger() { [[ ${1} == ?(-)+([0-9]) ]]; }
isFloat() { [[ ${1} == ?(-)@(+([0-9]).*([0-9])|*([0-9]).+([0-9]))?(E?(-|+)+([0-9])) ]]; }
isNumber() { isNaturalNumber $1 || isInteger $1 || isFloat $1; }
 2
Author: 3ronco,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-06 11:30:36

Używam następującego (dla liczb całkowitych):

## ##### constants
##
## __TRUE - true (0)
## __FALSE - false (1)
##
typeset -r __TRUE=0
typeset -r __FALSE=1

## --------------------------------------
## isNumber
## check if a value is an integer 
## usage: isNumber testValue 
## returns: ${__TRUE} - testValue is a number else not
##
function isNumber {
  typeset TESTVAR="$(echo "$1" | sed 's/[0-9]*//g' )"
  [ "${TESTVAR}"x = ""x ] && return ${__TRUE} || return ${__FALSE}
}

isNumber $1 
if [ $? -eq ${__TRUE} ] ; then
  print "is a number"
fi
 1
Author: Marnix,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-04 12:50:42

Wypróbowałam przepis ultrasawblade, który wydawał mi się najbardziej praktyczny i nie udało mi się. W końcu wymyśliłem inny sposób, oparty na zastępowaniu parametrów, tym razem z zastępowaniem regex:

[[ "${var//*([[:digit:]])}" ]]; && echo "$var is not numeric" || echo "$var is numeric"

Usuwa każdy znak: digit: class w $var i sprawdza, czy został nam pusty łańcuch, co oznacza, że oryginałem były tylko liczby.

To, co lubię w tym jednym jest jego mały rozmiar i elastyczność. W tej formie działa tylko dla nie-rozdzielone, bazowe liczby całkowite 10, choć z pewnością można użyć dopasowania wzorca, aby dopasować go do innych potrzeb.

 1
Author: ata,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-10-16 22:37:30

Quick & Dirty: wiem, że to nie jest najbardziej elegancki sposób, ale zwykle dodałem do niego zero i przetestowałem wynik. TAK:

function isInteger {
  [ $(($1+0)) != 0 ] && echo "$1 is a number" || echo "$1 is not a number"
 }

x=1;      isInteger $x
x="1";    isInteger $x
x="joe";  isInteger $x
x=0x16 ;  isInteger $x
x=-32674; isInteger $x   

$(($1+0)) zwróci 0 lub bomb Jeśli $1 nie jest liczbą całkowitą. na przykład:

function zipIt  { # quick zip - unless the 1st parameter is a number
  ERROR="not a valid number. " 
  if [ $(($1+0)) != 0 ] ; then  # isInteger($1) 
      echo " backing up files changed in the last $1 days."
      OUT="zipIt-$1-day.tgz" 
      find . -mtime -$1 -type f -print0 | xargs -0 tar cvzf $OUT 
      return 1
  fi
    showError $ERROR
}

Uwaga: chyba nigdy nie pomyślałem, aby sprawdzić pływaków lub mieszanych typów, które sprawią, że cały skrypt bomba... w moim przypadku nie chciałem, żeby to szło dalej. Pobawię się rozwiązaniem mrucci 'ego i regexem Duffy' ego-wydają się najbardziej wytrzymałe w bash ramy...

 1
Author: WWWIZARDS,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-12-24 06:02:38

Znalazłem dość krótką wersję:

function isnum()
{
    return `echo "$1" | awk -F"\n" '{print ($0 != $0+0)}'`
}
 1
Author: mary,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-13 14:07:44
  • Zmienna do sprawdzenia

    number=12345 LUB number=-23234 lub number=23.167 lub number=-345.234

  • Sprawdź numeryczne lub nie numeryczne

    echo $number | grep -E '^-?[0-9]*\.?[0-9]*$' > /dev/null

  • Zdecydować o dalszych działaniach w oparciu o status wyjścia z powyższego

    if [ $? -eq 0 ]; then echo "Numeric"; else echo "Non-Numeric"; fi

 1
Author: Atanu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-28 18:21:50

Aby wyłapać liczby ujemne:

if [[ $1 == ?(-)+([0-9.]) ]]
    then
    echo number
else
    echo not a number
fi
 1
Author: user28490,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-04 17:10:49

Możesz też użyć "let" w ten sposób:

[ ~]$ var=1
[ ~]$ let $var && echo "It's a number" || echo "It's not a number"
It\'s a number
[ ~]$ var=01
[ ~]$ let $var && echo "It's a number" || echo "It's not a number"
It\'s a number
[ ~]$ var=toto
[ ~]$ let $var && echo "It's a number" || echo "It's not a number"
It\'s not a number
[ ~]$ 

Ale wolę używać operatora "= ~ " Bash 3+ Jak kilka odpowiedzi w tym wątku.

 1
Author: Idriss Neumann,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-27 09:57:37

Używam printf jako innych wymienionych odpowiedzi, jeśli podasz format "% f "lub" % i " printf zrobi to za Ciebie. Łatwiejsze niż wymyślanie sprawdzeń, składnia jest prosta i krótka, a printf jest wszechobecny. Więc jego przyzwoity wybór moim zdaniem - można również użyć poniższego pomysłu, aby sprawdzić szereg rzeczy, jego nie tylko przydatne do sprawdzania liczb.

declare  -r CHECK_FLOAT="%f"  
declare  -r CHECK_INTEGER="%i"  

 ## <arg 1> Number - Number to check  
 ## <arg 2> String - Number type to check  
 ## <arg 3> String - Error message  
function check_number() { 
  local NUMBER="${1}" 
  local NUMBER_TYPE="${2}" 
  local ERROR_MESG="${3}"
  local -i PASS=1 
  local -i FAIL=0   
  case "${NUMBER_TYPE}" in 
    "${CHECK_FLOAT}") 
        if ((! $(printf "${CHECK_FLOAT}" "${NUMBER}" &>/dev/random;echo $?))); then 
           echo "${PASS}"
        else 
           echo "${ERROR_MESG}" 1>&2
           echo "${FAIL}"
        fi 
        ;;                 
    "${CHECK_INTEGER}") 
        if ((! $(printf "${CHECK_INTEGER}" "${NUMBER}" &>/dev/random;echo $?))); then 
           echo "${PASS}"
        else 
           echo "${ERROR_MESG}" 1>&2
           echo "${FAIL}"
        fi 
        ;;                 
                     *) 
        echo "Invalid number type format: ${NUMBER_TYPE} to check_number()." 1>&2
        echo "${FAIL}"
        ;;                 
   esac
} 

>$ var=45

>$ (($(check_number $var "${CHECK_INTEGER}" "Error: Found $var - An integer is required."))) && { echo "$var+5" | bc; }

 1
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-09 17:05:21

Podoba mi się odpowiedź Alberto Zaccagniego.

if [ "$var" -eq "$var" ] 2>/dev/null; then

Ważne warunki wstępne: - brak podpowiedzi - nie wywoływane re parsery - większość aplikacji shell nie używa liczb rzeczywistych

Ale jeśli $var jest złożona (np. dostęp do tablicy asocjacyjnej) i jeśli liczba będzie nieujemną liczbą całkowitą (większość przypadków użycia), to może to być bardziej efektywne?

if [ "$var" -ge 0 ] 2> /dev/null; then ..
 1
Author: user3895088,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-30 10:03:49
printf '%b' "-123\nABC" | tr '[:space:]' '_' | grep -q '^-\?[[:digit:]]\+$' && echo "Integer." || echo "NOT integer."

Usuń -\? w grep pasujący wzorzec, jeśli nie akceptujesz ujemnej liczby całkowitej.

 1
Author: Ane Dijitak,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-06 09:27:16

Kontynuując odpowiedź Dawida w z października ' 13, jeśli użyjesz {[1] } to może być lepiej

test_var=`expr $am_i_numeric \* 0` >/dev/null 2>&1
if [ "$test_var" = "" ]
then
    ......

Jeśli liczba pomnożona przez 1 daje tę samą wartość, (łącznie z liczbami ujemnymi). W przeciwnym razie otrzymasz null, które możesz przetestować na

 1
Author: Jon T,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-26 15:23:07

Zrobił to samo tutaj z wyrażeniem regularnym, które testuje całą część I część dziesiętną, oddzieloną kropką.

re="^[0-9]*[.]{0,1}[0-9]*$"

if [[ $1 =~ $re ]] 
then
   echo "is numeric"
else
  echo "Naahh, not numeric"
fi
 1
Author: Jerome,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-06 21:27:31