resumo: eu gostaria de usar uma bash
case
declaração (em outro código) para classificar as entradas para saber se elas são
- um número inteiro positivo
- um número inteiro negativo
- zero
- uma string vazia
- uma string não inteira
Segue o código executável, que está classificando corretamente as seguintes entradas:
- ''
word
a\nmultiline\nstring
2.1
-3
mas está classificando ambos os itens a seguir como ... inteiros negativos:-(
- 0
- 42
detalhes:
Salve o seguinte em um arquivo (por exemplo /tmp/integer_case_statement.sh
, ) chmod
, e execute-o:
#!/usr/bin/env bash
### This should be a simple `bash` `case` statement to classify inputs as
### {positive|negative|zero|non-} integers.
### Trying extglob, since my previous integer-match patterns failed.
### Gotta turn that on before *function definition* per https://stackoverflow.com/a/34913651/915044
shopt -s extglob
declare cmd=''
function identify() {
local -r it=${1} # no quotes in case it's multiline
# shopt -s extglob # can't do that here
case ${it} in
'')
# empty string, no need for `if [[ -z ...`
>&2 echo 'ERROR: null arg'
;;
?(-|+)+([[:digit:]]))
# it's an integer, so just say so and fallthrough
>&2 echo 'DEBUG: int(it), fallthrough'
;&
-+([[:digit:]]))
# it's negative: just return it
>&2 echo 'DEBUG: int(it) && (it < 0), returning it'
echo "${it}"
;;
0)
# it's zero: that's OK
>&2 echo 'DEBUG: int(it) && (it == 0), returning it'
echo '0'
;;
++([[:digit:]]))
# it's positive: just return it
>&2 echo 'DEBUG: int(it) && (it > 0), returning it'
echo "${it}"
;;
*)
# not an integer, just return it
>&2 echo 'DEBUG: !int(it)'
echo "${it}"
;;
esac
} # end function identify
echo -e "'bash --version'==${BASH_VERSION}\n"
echo "identify '':"
identify ''
echo
# > ERROR: null arg
echo 'identify word:'
identify word
echo
# > DEBUG: !int(it)
# > word
echo 'identify a
multiline
string:'
identify 'a
multiline
string'
echo
# > DEBUG: !int(it)
# > a
# > multiline
# > string
echo 'identify 2.1:'
identify 2.1
echo
# > DEBUG: !int(it)
# > 2.1
echo 'identify -3:'
identify -3
echo
# > DEBUG: int(it), fallthrough
# > DEBUG: int(it) && (it < 0), returning it
# > -3
echo 'identify 0:'
identify 0
echo
# > DEBUG: int(it), fallthrough
# > DEBUG: int(it) && (it < 0), returning it
# > 0
echo 'identify 42:'
identify 42
echo
# > DEBUG: int(it), fallthrough
# > DEBUG: int(it) && (it < 0), returning it
# > 42
exit 0
A saÃda atual está embutida no arquivo, mas para facilitar a leitura, aqui está minha saÃda atual separadamente:
'bash --version'==4.3.30(1)-release
identify '':
ERROR: null arg
identify word:
DEBUG: !int(it)
word
identify a
multiline
string:
DEBUG: !int(it)
a
multiline
string
identify 2.1:
DEBUG: !int(it)
2.1
identify -3:
DEBUG: int(it), fallthrough
DEBUG: int(it) && (it < 0), returning it
-3
identify 0:
DEBUG: int(it), fallthrough
DEBUG: int(it) && (it < 0), returning it
0
identify 42:
DEBUG: int(it), fallthrough
DEBUG: int(it) && (it < 0), returning it
42
As últimas 2 entradas são o meu problema: por que a instrução case está identificando
- 0 como um número inteiro negativo (em vez de 0)
- 42 como um número inteiro negativo (em vez de positivo)
? Sua ajuda é apreciada.
Resumo: Graças a
s/;&/;;&/
Também adicionei uma cláusula adicional para detectar zeros assinados e mais alguns casos de teste.
detalhes:
Salve este código aprimorado em um arquivo (por exemplo
/tmp/integer_case_statement.sh
, )chmod
, e execute-o:Nesta estação de trabalho Debian, as saÃdas acima atualmente:
Sua ajuda é apreciada!