Como diz o glenn , “ case
não usa expressões regulares, usa patterns ".
Como bash (1) diz,
case word in [ [(] pattern [ | pattern ] ... ) list ;; ] ... esac
A case
command first expands word
,
and tries to match it against each pattern
in turn,
using the same matching rules as for pathname expansion
(see Pathname Expansion below).
Da mesma forma, a especificação POSIX diz,
… each pattern … shall be compared against the expansion of word,
according to the rules described in Pattern Matching Notation …
Assim, os padrões são padrões de expansão de nome de caminho,
wildcards, a.k.a. globs, como em ls -l -- *.sh
ou rm -- *.bak
.
Claro, shopt -s extglob
e [[ … =~ … ]]
são a coisa mais legal desde o pão fatiado,
mas eles não são POSIX,
e pode ser útil saber como usar as ferramentas originais.
Durante anos, os programadores verificaram, por exemplo,
se uma string era um número
verificando se não foi não um número.
Você definiu um número para ser uma string que consiste
(inteiramente) de um ou mais dígitos.
Então, uma string não é um número se for nula,
ou se contiver um caractere que não seja um dígito.
Podemos testar essas condições com uma instrução case
da seguinte forma:
case "$1" in
("")
# null
︙
;;
(*[!0-9]*)
# contains non-numeric character(s)
︙
;;
(*)
# is a whole number (non-negative integer)
︙
esac
onde [!0-9]
é a maneira antiga de dizer [^0-9]
,
o que, obviamente, significa qualquer caractere que não seja um dígito.
( [!…]
e [^…]
trabalham no bash.
[!…]
é necessário para trabalhar com POSIX; o resultado de [^…]
não é especificado.)
Se você não se importa com o tipo de string que não é de um número,
você pode combinar os padrões não numéricos:
case "$1" in
("" | *[!0-9]*)
# not a number
︙
;;
(*)
# is a number
︙
esac
Como exercício,
aqui está uma declaração case
para lidar com qualquer tipo de número real -
para ser preciso, uma seqüência de um ou mais dígitos,
com opcionalmente um período ( .
) em algum lugar,
e, opcionalmente, um sinal de menos ( -
) no começo.
case "$1" in
(*[!-.0-9]*)
# contains non-numeric character(s)
;;
(*?-*)
# contains '-' somewhere other than the first position
;;
(*.*.*)
# contains multiple decimal points
;;
(*)
case "$1" in
(*[0-9]*)
# is a real number
;;
(*)
# not a number
esac
esac
Eu adicionei o case
-within-a- case
para verificar se a string, na verdade,
conter pelo menos um dígito.
Isso não foi necessário no exemplo inteiro
porque eu testei se a string era nula;
um teste que eu removi desta declaração.
Sem o segundo case
, um único -
ou um único .
-
ou mesmo -.
- qualificaria como um número.
Claro que poderíamos adicionar padrões para lidar com essas exceções,
mas isso pode ficar complexo.
(Por exemplo, eu quase postei essa resposta
sem perceber que -.
foi uma das exceções.)
Acredito que a abordagem acima é mais flexível e robusta.
É claro que os padrões não numéricos podem ser combinados aqui também:
(*[!-.0-9]* | *?-* | *.*.*)
.