Hay un par de cosas importantes que debes saber sobre la [[ ]]
construcción de bash . El primero:
La división de palabras y la expansión de nombre de ruta no se realizan en las palabras entre [[
y ]]
; Se realizan expansión de tilde, expansión de parámetros y variables, expansión aritmética, sustitución de comandos, sustitución de procesos y eliminación de comillas.
La segunda cosa:
Un operador binario adicional, '= ~', está disponible, ... la cadena a la derecha del operador se considera una expresión regular extendida y se empareja en consecuencia ... Cualquier parte del patrón se puede citar para forzar su coincidencia como una cuerda .
En consecuencia, $v
en cualquier lado de =~
se expandirá al valor de esa variable, pero el resultado no será dividido por palabras ni expandido por nombre de ruta. En otras palabras, es perfectamente seguro dejar las expansiones variables sin comillas en el lado izquierdo, pero debe saber que las expansiones variables ocurrirán en el lado derecho.
Entonces, si escribe:, [[ $x =~ [$0-9a-zA-Z] ]]
el $0
interior de la expresión regular a la derecha se expandirá antes de que se interprete la expresión regular, lo que probablemente hará que la expresión regular no se compile (a menos que la expansión de $0
extremos con un dígito o símbolo de puntuación cuyo valor ascii sea menor que un dígito). Si cita el lado derecho así [[ $x =~ "[$0-9a-zA-Z]" ]]
, entonces el lado derecho se tratará como una cadena ordinaria, no como una expresión regular. (y $0
aún se expandirá). Lo que realmente quieres en este caso es[[ $x =~ [\$0-9a-zA-Z] ]]
De manera similar, la expresión entre [[
y ]]
se divide en palabras antes de que se interprete la expresión regular. Por lo tanto, los espacios en la expresión regular deben escaparse o citarse. Si quería hacer coincidir letras, dígitos o espacios que podría utilizar: [[ $x =~ [0-9a-zA-Z\ ] ]]
. De manera similar, otros caracteres deben tener un escape, como #
, que iniciaría un comentario si no se cita. Por supuesto, puede poner el patrón en una variable:
pat="[0-9a-zA-Z ]"
if [[ $x =~ $pat ]]; then ...
Para las expresiones regulares que contienen muchos caracteres que necesitarían ser escapados o entre comillas para pasar por el lexer de bash, mucha gente prefiere este estilo. Pero cuidado: en este caso, no puede citar la expansión de la variable:
if [[ $x =~ "$pat" ]]; then ...
Finalmente, creo que lo que está tratando de hacer es verificar que la variable solo contiene caracteres válidos. La forma más sencilla de realizar esta comprobación es asegurarse de que no contiene un carácter no válido. En otras palabras, una expresión como esta:
valid='0-9a-zA-Z $%&#'
if [[ ! $x =~ [^$valid] ]]; then ...
!
niega la prueba, convirtiéndola en un operador "no coincide", y un [^...]
clase de carácter regex significa "cualquier carácter que no sea ...
".
La combinación de la expansión de parámetros y los operadores de expresiones regulares puede hacer que la sintaxis de la expresión regular de bash sea "casi legible", pero todavía existen algunos errores. (¿No son siempre?) Una de ellas es que no se podía poner ]
en $valid
, incluso si $valid
fueron citados, excepto en el principio. (Esa es una regla de expresiones regulares de Posix: si desea incluir ]
en una clase de carácter, debe ir al principio. -
Puede ir al principio o al final, por lo que si necesita ambos ]
y -
, debe comenzar con ]
y terminar con -
, que conduce a la expresión regular "yo sé lo que estoy haciendo" emoticon: [][-]
)