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 dash
POSIX 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
, zsh
POSIX sh
lub posh
( "a reimplementacja Bourne shell" sh
); case
konstrukt jest najbardziej powszechnie dostępne i wiarygodne:
case $1 in (*[!0-9]*|"") false ;; (*) true ;; esac
dash
? To działa dla mnie pod, bash
ale 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 posh
jest 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ć -eq
testu 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 SHLVL
lub 1+1
jest 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.2
i 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
match
nie \+
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
expr
implementacje 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 + 0
daje mi status wyjścia i 3 expr -12 + 0
i expr length + 0
dać mi stan 0 wyjścia z GNU expr ( + string
sił string
, aby być uznane jako ciąg z GNU expr
. expr "$a" - 0
Będzie działać lepiej).
-12
jest poprawną liczbą całkowitą i 9999999999999999999
spowodował 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\nbar
nie jest liczbą całkowitą, ale przejdzie ten test.