Como negar regex usando teste

Como negar regex usando teste

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 regexargumento, 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 regexnão devem ser citadas - a menos que a opção shell compat31esteja 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
  • regexdeve ser ancorado com ^...$, caso contrário foo1x1fubarseria considerada uma dimensão válida.

Lembre-se também de não usar intervalos como 0-9para 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 globasciirangesnão ajuda aqui. No Ubuntu 19.10 e no en_GB.UTF-8local, acho que bashcorresponde [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 shsintaxe 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 extglobe bashmesmo [[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]+..

informação relacionada