Comprobando si un número de entrada es un entero


31

Estoy tratando de verificar si una entrada es un número entero y la he revisado cientos de veces, pero no veo el error en esto. Por desgracia, no funciona, activa la instrucción if para todas las entradas (números / letras)

read scale
if ! [[ "$scale" =~ "^[0-9]+$" ]]
        then
            echo "Sorry integers only"
fi

He jugado con las citas, pero o me lo perdí o no hizo nada. ¿Qué hago mal? ¿Hay una manera más fácil de probar si una entrada es solo un INTEGER?

Respuestas:


25

Eliminar comillas

if ! [[ "$scale" =~ ^[0-9]+$ ]]
    then
        echo "Sorry integers only"
fi


Entonces hay un error. Con comillas, la expresión regular se trata como una cadena literal. Uno puede verificar eso conscale='^[0-9]+$'; [[ "$scale" == "^[0-9]+$" ]] && echo equal || echo "not equal"
jimmij

15

Usar -eqoperador del comando de prueba :

read scale
if ! [ "$scale" -eq "$scale" ] 2> /dev/null
then
    echo "Sorry integers only"
fi

No solo funciona bashsino también en cualquier shell POSIX. De la documentación de prueba POSIX :

n1 -eq  n2
    True if the integers n1 and n2 are algebraically equal; otherwise, false.

que comprueba si es cualquier número, no solo enteros
lonewarrior556

2
@ lonewarrior556: funciona solo para enteros, consulte: pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html . Supongo que dijiste cualquier número porque usas una nueva prueba en [[lugar de una prueba anterior [como la mía.
Cuonglm

Buena idea pero un poco ruidosa. Preferiría no tener que redirigir los errores a dev null.
Comodín el

2
@Wildcard: Sí, pagamos por la portabilidad.
Cuonglm

8

Para enteros sin signo utilizo:

read -r scale
[ -z "${scale//[0-9]}" ] && [ -n "$scale" ] || echo "Sorry integers only"

Pruebas:

$ ./test.sh
7
$ ./test.sh
   777
$ ./test.sh
a
Sorry integers only
$ ./test.sh
""
Sorry integers only
$ ./test.sh

Sorry integers only

1
Me gusta ese, ya que está hecho con builtins, rápido, y parece bastante posix ... Probé con un viejo shell (bash 2.0.5) y funciona perfectamente.
Olivier Dulac

¿Qué pasa con los espacios dentro del argumento? Como "086" .
0andriy

@ 0andriy Ver la segunda prueba.
raciasolvo

8

Como el OP parece querer solo enteros positivos:

[ "$1" -ge 0 ] 2>/dev/null

Ejemplos:

$ is_positive_int(){ [ "$1" -ge 0 ] 2>/dev/null && echo YES || echo no; }
$ is_positive_int word
no
$ is_positive_int 2.1
no
$ is_positive_int -3
no
$ is_positive_int 42
YES

Tenga en cuenta que [se requiere una sola prueba:

$ [[ "word" -eq 0 ]] && echo word equals zero || echo nope
word equals zero
$ [ "word" -eq 0 ] && echo word equals zero || echo nope
-bash: [: word: integer expression expected
nope

Esto se debe a que la desreferenciación ocurre con [[:

$ word=other
$ other=3                                                                                                                                                                                  
$ [[ $word -eq 3 ]] && echo word equals other equals 3
word equals other equals 3

esta es la verdadera respuesta ... otros fallaron
Scott Stensland

3
( scale=${scale##*[!0-9]*}
: ${scale:?input must be an integer}
) || exit

Eso hace la verificación y genera su error.


OPTINDTambién es bueno aquí. solo saiyan.
mikeserv

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.