Isso está sintaticamente errado:
#!/usr/bin/env bash
dimension="4x5"
if [[ "$dimension" !=~ '[0-9]x[0-9]' ]]; then
echo 'wtf meng, the dimension needs an "x" in it.'
return 1;
fi
o texto acima tem sintaxe incorreta... então minha pergunta é: existe uma maneira de fazer!=~
... Acho que é !~
? Se isso for verdade, chega de regras de negação lulz. Tudo bem, testei e !~
também não funciona..
Responder1
Não há operadores !=~
ou !~
para a [[
palavra-chave. Em vez disso, negue o resultado da comparação:
[[ ! "string" =~ regex ]]
Quanto à citação do regex
argumento, o manual afirma:
Qualquer parte do padrão pode ser citada para forçar a correspondência da parte citada como uma string.
Portanto, partes de expressões regulares de regex
não devem ser citadas - a menos que a opção shell compat31
esteja definida:
shopt
...compat31
Se definido, o bash muda seu comportamento para o da versão 3.1 em relação aos argumentos citados para o operador
[[
do comando condicional=~
Para o exemplo dado, tente:
if [[ ! "$dimension" =~ ^[0123456789]+x[0123456789]+$ ]]; then
printf '%s %s\n' "'$dimension'" 'is not a valid dimension.'
fi
regex
deve ser ancorado com^...$
, caso contráriofoo1x1fubar
seria considerada uma dimensão válida.
Lembre-se também de não usar intervalos como 0-9
para validação de entrada, especialmente se for para higienização em contextos sensíveis à segurança, pois em muitos locais, esses intervalos incluem muito mais caracteres (ou possivelmente elementos de agrupamento feitos de vários caracteres) do que historicamente (e ainda faz no código do idioma C/POSIX).
Pois =~
, bash
's globasciiranges
não ajuda aqui. No Ubuntu 19.10 e no en_GB.UTF-8
local, acho que bash
corresponde [0-9]
a 1.040 caracteres diferentes, além de 0123456789, com ou sem globasciiranges
. Pelo menos no meu caso todos eles têm alguma relação com dígitos decimais de 0 a 8, mas isso nem é garantido em geral.
Por outro lado, [[:digit:]]
e [0123456789]
corresponde apenas a esses 10 e deveria em qualquer sistema compatível com POSIX.
Você também pode fazer isso usando sh
sintaxe padrão e padrões curinga com algo como:
valid_geometry() case $1 in
(*[!x0123456789]* | *x | x* | *x*x*) false;;
(*x*) true;;
(*) false;;
esac
if ! valid_geometry "$dimension"; then
...
fi
Ou com ksh globs (como também suportado por bash -O extglob
e bash
mesmo [[
sem extglob
) com:
if [[ $dimension != +([0123456789])x+([0123456789]) ]]; then
...
fi
Responder2
Tudo bem, então isso parece funcionar:
if [[ ! "$dimension" =~ [0-9]+x[0-9]+ ]]; then
echo 'wtf meng, the dimension needs an "x" in it.'
exit 1;
fi
mas estou me perguntando por que colocá-lo entre aspas simples não funciona:
if [[ ! "$dimension" =~ '[0-9]+x[0-9]+' ]]; then
echo 'wtf meng, the dimension needs an "x" in it.'
exit 1;
fi
aqui está minha solução:
dimension="3x5"
regex='[0-9]+x[0-9]+'
if [[ ! "$dimension" =~ $regex ]]; then
echo 'wtf meng, the dimension needs an "x" in it.'
exit 1;
fi
Agora você pode usar aspas simples para citar o regex, mas deve evitar aspas duplas ao fazer referência a $regex de dentro de [[ ]]. No entanto, ainda estou curioso para saber se existe uma abreviação para [0-9]+
..