Cómo negar expresiones regulares usando la prueba

Cómo negar expresiones regulares usando la prueba

Esto es sintácticamente incorrecto:

#!/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

lo anterior tiene una sintaxis incorrecta... entonces mi pregunta es: ¿hay alguna manera de hacerlo?!=~

...Supongo que es !~? Si eso es cierto, hasta aquí las reglas de negación lulz. Muy bien, lo probé y !~tampoco funciona.

Respuesta1

No hay operadores !=~u !~para la [[palabra clave. En lugar de ello, niega el resultado de la comparación:

[[ ! "string" =~ regex ]]

Respecto a citar el regexargumento, el manual dice:

Se puede citar cualquier parte del patrón para forzar que la parte citada coincida como una cadena.

Por lo tanto, las partes de expresiones regulares de regexno deben citarse, a menos que compat31esté configurada la opción de shell:

shopt...compat31

Si se establece, bash cambia su comportamiento al de la versión 3.1 con respecto a los argumentos citados para el operador [[del comando condicional.=~

Para el ejemplo dado, intente:

if [[ ! "$dimension" =~ ^[0123456789]+x[0123456789]+$ ]]; then
    printf '%s %s\n' "'$dimension'" 'is not a valid dimension.'
fi
  • regexdebe estar anclado con ^...$, de lo contrario foo1x1fubarse considerará una dimensión válida.

También recuerde no usar rangos como 0-9para la validación de entradas, especialmente si es para desinfección en contextos sensibles a la seguridad, ya que en muchas configuraciones regionales, estos rangos incluyen muchos más caracteres (o posiblemente elementos de recopilación compuestos por varios caracteres) que históricamente (y todavía lo hago en la configuración regional C/POSIX).

Porque =~' bashs globasciirangesno ayuda aquí. En Ubuntu 19.10 y en la en_GB.UTF-8configuración regional, encuentro bashcoincidencias [0-9]en 1040 caracteres diferentes además de 0123456789, con o sin globasciiranges. Al menos en mi caso, todos tienen alguna relación con los dígitos decimales del 0 al 8, pero eso ni siquiera está garantizado en general.

Por otro lado, [[:digit:]]y [0123456789]coincide solo con esos 10 y debería hacerlo en cualquier sistema compatible con POSIX.

También puedes hacerlo usando shsintaxis estándar y patrones comodín con algo como:

valid_geometry() case $1 in
  (*[!x0123456789]* | *x | x* | *x*x*) false;;
  (*x*) true;;
  (*) false;;
esac
if ! valid_geometry "$dimension"; then
   ...
fi

O con ksh globs (como también lo admite bash -O extgloband bash's [[even without extglob) con:

if [[ $dimension != +([0123456789])x+([0123456789]) ]]; then
  ...
fi

Respuesta2

Muy bien, esto parece funcionar:

if [[ ! "$dimension" =~ [0-9]+x[0-9]+ ]]; then
 echo 'wtf meng, the dimension needs an "x" in it.'
 exit 1;
fi

pero me pregunto por qué envolverlo entre comillas simples no funciona:

if [[ ! "$dimension" =~ '[0-9]+x[0-9]+' ]]; then
 echo 'wtf meng, the dimension needs an "x" in it.'
 exit 1;
fi

aquí está mi solución:

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

Ahora puede utilizar comillas simples para citar la expresión regular, pero debe evitar las comillas dobles cuando haga referencia a $regex desde [[ ]]. Sin embargo, todavía tengo curiosidad por saber si hay una abreviatura para [0-9]+...

información relacionada