/ bin / dash: sprawdź, czy 1 $ jest liczbą


12

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:


12

Następujące wykrywają liczby całkowite, dodatnie lub ujemne, i działają pod dashPOSIX i są:

opcja 1

echo "$1" | grep -Eq '^[+-]?[0-9]+$' && echo "It's an integer"

Opcja 2

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

5
Co jeśli ciąg zawiera znaki nowej linii? foo\n123\nbarnie jest liczbą całkowitą, ale przejdzie ten test.
— godlygeek,

3
To znaczy wersja grep. Wersja skrzynki wygląda poprawnie.
— godlygeek,

5

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

Testowałeś to pod dash? To działa dla mnie pod, bashale nie dash.
— John1024,

Tak, przetestowałem to również na moim systemie dash; aby przesłuchać wynik dodany echo $?po poleceniu case.
— Janis,

Zrobiłem to samo (stabilna Debian), ale nie miałem radości. Aby uzyskać pełny przykład, który działa dla mnie pod moją deską rozdzielczą, zobacz moją Opcję 2 .
— John1024,

Hmm, nie mam dostępnej oryginalnej powłoki Bourne'a do przetestowania. Dokumenty, które sprawdziłem na temat „funkcji [w ksh] nie w powłoce Bourne'a” przynajmniej o tym nie wspominają, więc zakładam, że tam były. Nie? - Następnie pomiń nawias wiodący. - OTOH posh(„reimplementacja powłoki Bourne'a”) również nie ma problemu z tym rozwiązaniem.
— Janis,

1
@mikeserv; Istnieje kilka powodów, dla których używam zawsze pasujących nawiasów 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.
— Janis,

1

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

1
Powiedziałby również, że " 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ą.
— Stéphane Chazelas,

0

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)).


1
dash nie ma[[
— glenn jackman

@glennjackman Whoops. To ma $(( ... ))? Jeśli tak, moja odpowiedź powinna być nadal istotna, muszę tylko dodać dodatkowe cytaty.
— godlygeek,

to twoja odpowiedź: dowiedz się.
— glenn jackman

Wygląda na to, że tak, więc moja zaktualizowana wersja powinna załatwić sprawę. Nie mam jednak umiejętności testowania, więc daj mi znać, jeśli coś mi umknie.
— godlygeek,

Próbowałem: check_if_number 1.2i funkcja zwróciła: dash: 3: arithmetic expression: expecting EOF: "1.2"
— John1024

0

Być może z expr?

if expr match "$1" '^\([0-9]\+\)$' > /dev/null; then
  echo "integer"
else 
  echo "non-integer"
fi

POSIX też matchnie \+jest. Powiedziałby również, że 0 nie jest liczbą. Chceszexpr "x$1" : 'x[0-9]\{1,\}$'
— Stéphane Chazelas,

0

W systemie POSIX możesz użyć expr :

$ a=a
$ expr "$a" - 0 >/dev/null 2>&1
$ [ "$?" -lt 2 ] && echo Integer || echo Not Integer

Powie, że 0 nie jest liczbą całkowitą (i powiedz -12, że rozwiązanie bash OP zostanie odrzucone). Niektóre 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ą.
— Stéphane Chazelas

W moim teście działa przynajmniej w Debianie i OSX. Mówi, że liczba całkowita dla 0. Posix zapewnia, że ​​$ a musi być poprawnym wyrażeniem (liczba całkowita) dla wyrażenia arytmetycznego.
— cuonglm

Och tak, przepraszam, przeoczyłem twój test za $? <2. Wciąż 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).
— Stéphane Chazelas

@ StéphaneChazelas: Och, tak, zaktualizowałem moją odpowiedź. Myślę, że -12jest poprawną liczbą całkowitą i 9999999999999999999spowodował przepełnienie.
— cuonglm

0

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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.