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?

lonewarrior556
fonte

Respostas:

25

Remover aspas

if ! [[ "$scale" =~ ^[0-9]+$ ]]
    then
        echo "Sorry integers only"
fi
jimmij
fonte
stackoverflow.com/questions/806906/... teve a citações para trás
lonewarrior556
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.
cuonglm
fonte
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
raciasolvo
fonte
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
Tom Hale
fonte
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.

mikeserv
fonte
OPTINDaqui é bom também. apenas saiyan.
mikeserv