Un approccio consiste nell'utilizzare un'espressione regolare, in questo modo:
re='^[0-9]+$'
if ! [[ $yournumber =~ $re ]] ; then
echo "error: Not a number" >&2; exit 1
fi
Se il valore non è necessariamente un numero intero, valuta la possibilità di modificare la regex in modo appropriato; ad esempio:
^[0-9]+([.][0-9]+)?$
...oppure, per gestire i numeri con un segno:
^[+-]?[0-9]+([.][0-9]+)?$
Nessuno ha suggerito il pattern matching esteso di bash:
[[ $1 == ?(-)+([0-9]) ]] && echo "$1 is an integer"
o utilizzando una classe di caratteri POSIX:
[[ $1 == ?(-)+([[:digit:]]) ]] && echo "$1 is an integer"
La seguente soluzione può essere utilizzata anche in shell di base come Bourne senza la necessità di espressioni regolari. Fondamentalmente qualsiasi operazione di valutazione del valore numerico che utilizza non numeri risulterà in un errore che sarà implicitamente considerato falso nella shell:
"$var" -eq "$var"
come in:
#!/bin/bash
var=a
if [ -n "$var" ] && [ "$var" -eq "$var" ] 2>/dev/null; then
echo number
else
echo not a number
fi
Puoi anche provare per $? il codice di ritorno dell'operazione che è più esplicito:
[ -n "$var" ] && [ "$var" -eq "$var" ] 2>/dev/null
if [ $? -ne 0 ]; then
echo $var is not number
fi
Il reindirizzamento dell'errore standard è lì per nascondere il messaggio "espressione intera attesa" che bash stampa nel caso in cui non abbiamo un numero.
AVVERTIMENTI (grazie ai commenti qui sotto):
- I numeri con punti decimali non identificati come "numeri" validi
- Usando
[[ ]]
invece di[ ]
restituirà sempretrue
- La maggior parte delle shell non Bash valuterà sempre questa espressione come
true
- Il comportamento in Bash non è documentato e potrebbe quindi cambiare senza preavviso
- Se il valore include spazi dopo il numero (ad es. "1 a") produce un errore, come
bash: [[: 1 a: syntax error in expression (error token is "a")
- Se il valore è lo stesso di var-name (ad es. i="i"), produce un errore, come
bash: [[: i: expression recursion level exceeded (error token is "i")
Senza bashismi (funziona anche nel System V sh),
case $string in
''|*[!0-9]*) echo bad ;;
*) echo good ;;
esac
Questo rifiuta le stringhe vuote e le stringhe che non contengono cifre, accettando tutto il resto.
I numeri negativi o in virgola mobile richiedono un lavoro aggiuntivo. Un'idea è quella di escludere -
/ .
nel primo pattern "cattivo" e aggiungi altri pattern "cattivi" che ne contengono gli usi inappropriati (?*-*
/ *.*.*
)