Un enfoque es usar una expresión regular, así:
re='^[0-9]+$'
if ! [[ $yournumber =~ $re ]] ; then
echo "error: Not a number" >&2; exit 1
fi
Si el valor no es necesariamente un número entero, considere modificar la expresión regular de manera adecuada; por ejemplo:
^[0-9]+([.][0-9]+)?$
...o, para manejar números con un signo:
^[+-]?[0-9]+([.][0-9]+)?$
Nadie sugirió la coincidencia de patrones extendida de bash:
[[ $1 == ?(-)+([0-9]) ]] && echo "$1 is an integer"
o usando una clase de carácter POSIX:
[[ $1 == ?(-)+([[:digit:]]) ]] && echo "$1 is an integer"
La siguiente solución también se puede usar en shells básicos como Bourne sin necesidad de expresiones regulares. Básicamente, cualquier operación de evaluación de valores numéricos que no utilice números dará como resultado un error que se considerará implícitamente como falso en el shell:
"$var" -eq "$var"
como en:
#!/bin/bash
var=a
if [ -n "$var" ] && [ "$var" -eq "$var" ] 2>/dev/null; then
echo number
else
echo not a number
fi
¿También puedes probar por $? el código de retorno de la operación que es más explícito:
[ -n "$var" ] && [ "$var" -eq "$var" ] 2>/dev/null
if [ $? -ne 0 ]; then
echo $var is not number
fi
La redirección del error estándar está ahí para ocultar el mensaje de "expresión entera esperada" que bash imprime en caso de que no tengamos un número.
ADVERTENCIAS (gracias a los comentarios a continuación):
- Los números con puntos decimales no identificado como "números" válidos
- Usando
[[ ]]
en lugar de[ ]
siempre evaluará atrue
- La mayoría de los shells que no son Bash siempre evaluarán esta expresión como
true
- El comportamiento en Bash no está documentado y, por lo tanto, puede cambiar sin previo aviso
- Si el valor incluye espacios después del número (por ejemplo, "1 a") produce un error, como
bash: [[: 1 a: syntax error in expression (error token is "a")
- Si el valor es el mismo que var-name (por ejemplo, i="i"), produce un error, como
bash: [[: i: expression recursion level exceeded (error token is "i")
Sin bashisms (funciona incluso en System V sh),
case $string in
''|*[!0-9]*) echo bad ;;
*) echo good ;;
esac
Esto rechaza cadenas vacías y cadenas que no contienen dígitos, aceptando todo lo demás.
Los números negativos o de coma flotante necesitan un trabajo adicional. Una idea es excluir -
/ .
en el primer patrón "malo" y agregue más patrones "malos" que contengan usos inapropiados de ellos (?*-*
/ *.*.*
)