Verificando se um número de entrada é um número inteiro


31

Estou tentando verificar se uma entrada é um número inteiro e já repassei centenas de vezes, mas não vejo o erro nisso. Infelizmente, ele não funciona, ele dispara a instrução if para todas as entradas (números / letras)

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

Eu brinquei com as aspas, mas perdi ou não fez nada. O que eu faço de errado? Existe uma maneira mais fácil de testar se uma entrada é apenas um INTEGER?

Respostas:


25

Remover aspas

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


Portanto, há um erro. Entre aspas, o regexp é tratado como uma string literal. Pode-se verificar isso comscale='^[0-9]+$'; [[ "$scale" == "^[0-9]+$" ]] && echo equal || echo "not equal"
jimmij

15

Use o -eqoperador do comando test :

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

Ele não apenas funciona, bashmas também qualquer shell POSIX. Da documentação de teste POSIX :

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

que verifica se os seus qualquer número, e não apenas números inteiros
lonewarrior556

2
@ lonewarrior556: Funciona apenas para números inteiros, consulte: pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html . Eu acho que você disse para qualquer número, porque você usa novo teste em [[vez de teste antigo [como o meu.
cuonglm

Boa ideia, mas um pouco barulhenta. Eu preferiria não ter que redirecionar erros para dev null.
Curinga

2
@Wildcard: Sim, pagamos pela portabilidade.
cuonglm

8

Para números inteiros não assinados, eu uso:

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

Testes:

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

Sorry integers only

11
Eu gosto desse, pois ele é feito com builtins, rápido e parece bastante posix ... Tentei usar um shell antigo (bash 2.0.5) e ele funciona perfeitamente.
Olivier Dulac

E quanto aos espaços dentro do argumento? Como "086" .
0andriy

@ 0andriy Veja o segundo teste.
raciasolvo

8

Como o OP parece querer apenas números inteiros positivos:

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

Exemplos:

$ 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

Observe que [é necessário um único teste:

$ [[ "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

Isso ocorre porque a desreferenciação ocorre com [[:

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

esta é a verdadeira resposta ... outros falharam
Scott Stensland

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

Isso faz a verificação e gera seu erro.


OPTINDaqui é bom também. apenas saiyan.
mikeserv

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.