Es que no consigo averiguar cómo hago para asegurarme de que un argumento pasado a mi script es un número o no.
Todo lo que quiero hacer es algo así:
test *isnumber* $1 && VAR=$1 || echo "need a number"
¿Alguna ayuda?
Es que no consigo averiguar cómo hago para asegurarme de que un argumento pasado a mi script es un número o no.
Todo lo que quiero hacer es algo así:
test *isnumber* $1 && VAR=$1 || echo "need a number"
¿Alguna ayuda?
Un enfoque es utilizar una expresión regular, como la siguiente:
re='^[0-9]+$'
if ! [[ $yournumber =~ $re ]] ; then
echo "error: Not a number" >&2; exit 1
fi
Si el valor no es necesariamente un entero, considere la posibilidad de modificar la expresión regular de forma adecuada; por ejemplo
^[0-9]+([.][0-9]+)?$
...o, para manejar los números con un signo:
^[+-]?[0-9]+([.][0-9]+)?$
Sin bashismos (funciona incluso en el Sistema V sh),
case $string in
''|*[!0-9]*) echo bad ;;
*) echo good ;;
esac
Esto rechaza las cadenas vacías y las que no contienen dígitos, aceptando todo lo demás.
Los números negativos o de punto flotante necesitan un trabajo adicional. Una idea es excluir -
/ .
en el primer patrón "malo" y añadir más patrones "malos" que contengan los usos inadecuados de los mismos ( ?*-*
/ *.*.*
)
La siguiente solución también puede utilizarse 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 sean números dará lugar a un error que se considerará implícitamente como falso en 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 se puede probar 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 "integer expression expected" que bash imprime en caso de que no tengamos un número.
CAVEATS (gracias a los comentarios de abajo):
[[ ]]
en lugar de [ ]
siempre se evaluará a true
true
bash: [[: 1 a: syntax error in expression (error token is "a")
bash: [[: i: expression recursion level exceeded (error token is "i")
Esto comprueba si un número es un entero no negativo y es a la vez Shell independiente (es decir, sin bashismos) y utiliza sólo Shell built-ins:
INCORRECTO.
Como esta primera respuesta (abajo) permite números enteros con caracteres en ellos siempre que los primeros no sean los primeros en la variable.
[ -z "${num##[0-9]*}" ] && echo "is a number" || echo "is not a number";
CORRECTO .
Como jilles comentado y sugerido en su respuesta esta es la forma correcta de hacerlo usando Shell-patrones.
[ ! -z "${num##*[!0-9]*}" ] && echo "is a number" || echo "is not a number";
Me sorprenden las soluciones que analizan directamente los formatos numéricos en Shell. Shell no se adapta bien a esto, siendo un DSL para controlar archivos y procesos. Hay amplios parsers de números un poco más abajo, por ejemplo:
isdecimal() {
# filter octal/hex/ord()
num=$(printf '%s' "$1" | sed "s/^0*\([1-9]\)/\1/; s/'/^/")
test "$num" && printf '%f' "$num" >/dev/null 2>&1
}
Cambie "%f" por el formato que desee.
Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.