Jaki byłby najlepszy sposób sprawdzenia, czy 1 $ jest liczbą całkowitą w / bin / dash?
W bashu mogłem:
[[ $1 =~ ^([0-9]+)$ ]]
Ale to nie wydaje się być zgodne z POSIX i dash tego nie obsługuje
Jaki byłby najlepszy sposób sprawdzenia, czy 1 $ jest liczbą całkowitą w / bin / dash?
W bashu mogłem:
[[ $1 =~ ^([0-9]+)$ ]]
Ale to nie wydaje się być zgodne z POSIX i dash tego nie obsługuje
Odpowiedzi:
Następujące wykrywają liczby całkowite, dodatnie lub ujemne, i działają pod dashPOSIX i są:
echo "$1" | grep -Eq '^[+-]?[0-9]+$' && echo "It's an integer"
case "${1#[+-]}" in
''|*[!0-9]*)
echo "Not an integer" ;;
*)
echo "Integer" ;;
esac
Lub przy niewielkim użyciu polecenia :(nop):
! case ${1#[+-]} in *[!0-9]*) :;; ?*) ! :;; esac && echo Integer
Niezależnie od tego dash, bash, ksh, zshPOSIX shlub posh( "a reimplementacja Bourne shell" sh ); casekonstrukt jest najbardziej powszechnie dostępne i wiarygodne:
case $1 in (*[!0-9]*|"") false ;; (*) true ;; esac
dash? To działa dla mnie pod, bashale nie dash.
dash; aby przesłuchać wynik dodany echo $?po poleceniu case.
posh(„reimplementacja powłoki Bourne'a”) również nie ma problemu z tym rozwiązaniem.
case; jednym z powodów jest opisany przez ciebie błąd, innym jest to, że w edytorach, które mają funkcje oparte na dopasowywaniu nawiasów (vim), zapewnia ono o wiele lepsze wsparcie, i osobiście uważam, że lepiej jest je dopasować. - WRT poshjest POSIX; cóż, cytat ze strony podręcznika, który podałem, sugeruje coś innego, ale chyba nie można polegać na tak nieformalnych stwierdzeniach. Stara skorupa Bourne'a i tak nie jest już tak znacząca teraz, gdy jesteśmy w erze POSIX.
Możesz użyć -eqtestu na łańcuchu, z samym sobą:
$ dash -c 'a="a"; if [ "$a" -eq "$a" ] ; then echo number; else echo not a number; fi'
dash: 1: [: Illegal number: a
not a number
$ dash -c 'a="0xa"; if [ "$a" -eq "$a" ] ; then echo number; else echo not a number; fi'
dash: 1: [: Illegal number: 0xa
not a number
$ dash -c 'a="-1"; if [ "$a" -eq "$a" ] ; then echo number; else echo not a number; fi'
number
Jeśli komunikat o błędzie stanowi problem, przekieruj wyjście błędu do /dev/null:
$ dash -c 'a="0xa"; [ "$a" -eq "$a" ] 2>/dev/null|| echo no'
no
" 023 "jest to liczba. Zauważ, że działa z myślnikiem, ale nie ze wszystkimi innymi powłokami POSIX, ponieważ zachowanie nie jest określone, jeśli operandy są liczbami całkowitymi dziesiętnymi. Na przykład z ksh powiedziałoby to SHLVLlub 1+1jest liczbą.
Spróbuj użyć go jako rozszerzenia arytmetycznego i sprawdź, czy działa. W rzeczywistości musisz być nieco bardziej rygorystyczny, ponieważ rozszerzenia arytmetyczne ignorowałyby na przykład spacje początkowe i końcowe. Więc wykonaj interpretację arytmetyczną i upewnij się, że rozwinięty wynik dokładnie pasuje do oryginalnej zmiennej.
check_if_number()
{
if [ "$1" = "$((${1}))" ] 2>/dev/null; then
echo "Number!"
else
echo "not a number"
fi
}
Spowodowałoby to również przyjęcie liczb ujemnych - jeśli naprawdę chcesz je wykluczyć, dodaj dodatkowe pole wyboru dla $((${1} >= 0)).
[[
$(( ... ))? Jeśli tak, moja odpowiedź powinna być nadal istotna, muszę tylko dodać dodatkowe cytaty.
check_if_number 1.2i funkcja zwróciła: dash: 3: arithmetic expression: expecting EOF: "1.2"
Być może z expr?
if expr match "$1" '^\([0-9]\+\)$' > /dev/null; then
echo "integer"
else
echo "non-integer"
fi
matchnie \+jest. Powiedziałby również, że 0 nie jest liczbą. Chceszexpr "x$1" : 'x[0-9]\{1,\}$'
W systemie POSIX możesz użyć expr :
$ a=a
$ expr "$a" - 0 >/dev/null 2>&1
$ [ "$?" -lt 2 ] && echo Integer || echo Not Integer
exprimplementacje powiedzą, że 999999999999999999999 nie jest liczbą całkowitą. POSIX nie daje żadnej gwarancji, że to zadziała. W praktyce przynajmniej w systemie GNU powiedzą, że „długość” jest liczbą całkowitą.
expr 9999999999999999999 + 0daje mi status wyjścia i 3 expr -12 + 0i expr length + 0dać mi stan 0 wyjścia z GNU expr ( + stringsił string, aby być uznane jako ciąg z GNU expr. expr "$a" - 0Będzie działać lepiej).
-12jest poprawną liczbą całkowitą i 9999999999999999999spowodował przepełnienie.
Oto prosta funkcja stosując tę samą metodę jak Muru jest odpowiedź :
IsInteger() # usage: IsInteger string
{ # returns: flag
[ "$1" -eq "$1" ] 2> /dev/null
}
Przykład:
p= n=2a3; IsInteger $n || p="n't" ; printf "'%s' is%s an integer\n" "$n" "$p"
p= n=23; IsInteger $n || p="n't" ; printf "'%s' is%s an integer\n" "$n" "$p"
Wynik:
'2a3' isn't an integer
'23' is an integer
foo\n123\nbarnie jest liczbą całkowitą, ale przejdzie ten test.