Quale sarebbe il modo migliore per verificare se $ 1 è un numero intero in / bin / dash?
In bash, potrei fare:
[[ $1 =~ ^([0-9]+)$ ]]
Ma questo non sembra conforme a POSIX e il trattino non lo supporta
Quale sarebbe il modo migliore per verificare se $ 1 è un numero intero in / bin / dash?
In bash, potrei fare:
[[ $1 =~ ^([0-9]+)$ ]]
Ma questo non sembra conforme a POSIX e il trattino non lo supporta
Risposte:
I seguenti rilevano numeri interi, positivi o negativi, e funzionano sotto dash
e sono POSIX:
echo "$1" | grep -Eq '^[+-]?[0-9]+$' && echo "It's an integer"
case "${1#[+-]}" in
''|*[!0-9]*)
echo "Not an integer" ;;
*)
echo "Integer" ;;
esac
Oppure, con un piccolo uso del :
comando (nop):
! case ${1#[+-]} in *[!0-9]*) :;; ?*) ! :;; esac && echo Integer
Sia dash
, bash
, ksh
, zsh
, POSIX sh
, o posh
( "una reimplementazione del guscio Bourne" sh
); il case
costrutto è il più ampiamente disponibile e affidabile:
case $1 in (*[!0-9]*|"") false ;; (*) true ;; esac
dash
? Funziona per me sotto bash
ma non dash
.
dash
; per interrogare il risultato che ho aggiunto echo $?
dopo il comando case.
posh
("una reimplementazione della shell Bourne"), tuttavia, non ha problemi con questa soluzione.
case
; un motivo è il bug che descrivi, un altro che negli editor che hanno funzionalità che si basano sulla parentesi corrispondente (vim) offre un supporto molto migliore, e non ultimo trovo che sia meglio leggibile personalmente averli corrispondenti. - WRT posh
essendo POSIX; beh, la citazione dalla pagina man che ho dato ha suggerito qualcos'altro, ma comunque non si può fare affidamento su tali dichiarazioni informali. Il vecchio bourne shell non è più così significativo ora che siamo nell'era POSIX.
Puoi usare il -eq
test sulla stringa, con se stesso:
$ 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
Se il messaggio di errore è un problema, reindirizzare l'output dell'errore a /dev/null
:
$ dash -c 'a="0xa"; [ "$a" -eq "$a" ] 2>/dev/null|| echo no'
no
" 023 "
è un numero. Si noti che funziona con trattino, ma non con tutte le altre shell POSIX poiché il comportamento non è specificato se gli operandi sono numeri decimali di nota. Ad esempio con ksh, direbbe che SHLVL
o 1+1
è un numero.
Prova a usarlo come espansione aritmetica e vedi se funziona. In realtà, devi essere un po 'più rigoroso di quello, perché le espansioni aritmetiche ignorerebbero gli spazi iniziali e finali, ad esempio. Quindi esegui un'espansione aritmetica e assicurati che il risultato espanso corrisponda esattamente alla variabile originale.
check_if_number()
{
if [ "$1" = "$((${1}))" ] 2>/dev/null; then
echo "Number!"
else
echo "not a number"
fi
}
Questo accetterebbe anche numeri negativi - se vuoi davvero escluderli, aggiungi un ulteriore controllo per $((${1} >= 0))
.
[[
$(( ... ))
? In tal caso, la mia risposta dovrebbe essere ancora materialmente corretta, ho solo bisogno di aggiungere alcune citazioni extra.
check_if_number 1.2
e la funzione è tornata: dash: 3: arithmetic expression: expecting EOF: "1.2"
Forse con expr
?
if expr match "$1" '^\([0-9]\+\)$' > /dev/null; then
echo "integer"
else
echo "non-integer"
fi
match
né \+
POSIX. Direbbe anche che 0 non è un numero. Voleteexpr "x$1" : 'x[0-9]\{1,\}$'
Nel sistema POSIX, è possibile utilizzare expr :
$ a=a
$ expr "$a" - 0 >/dev/null 2>&1
$ [ "$?" -lt 2 ] && echo Integer || echo Not Integer
expr
implementazioni diranno che 9999999999999999999 non è un numero intero. POSIX non offre alcuna garanzia sul funzionamento. In pratica, almeno su un sistema GNU, dirà che "lunghezza" è un numero intero.
expr 9999999999999999999 + 0
Mi dà ancora uno stato di uscita 3 expr -12 + 0
e expr length + 0
mi dà uno stato di uscita 0 con GNU expr (le + string
forze string
da considerare come una stringa con GNU expr
. expr "$a" - 0
Funzionerebbero meglio).
-12
sia un numero intero valido e ha 9999999999999999999
dato un overflow.
Ecco una semplice funzione che utilizza lo stesso metodo della risposta di Muru :
IsInteger() # usage: IsInteger string
{ # returns: flag
[ "$1" -eq "$1" ] 2> /dev/null
}
Esempio:
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"
Produzione:
'2a3' isn't an integer
'23' is an integer
foo\n123\nbar
non è un numero intero, ma supererebbe questo test.