Coincidencia de patrones de cadenas con = ~

Tengo problemas para entender la coincidencia de patrones de cadenas con = ~ en bash .

Escribí la siguiente función ( no se alarme, es solo experimentar, no un enfoque de seguridad con md5sum):

md5 () { [[ "$(md5sum $1)" =~ $2* ]] && echo fine || echo baarr; } 

y lo probó con alguna entrada. Aquí una referencia:

md5sum wp.laenderliste b1eb0d822e8d841249e3d68eeb3068d3 wp.laenderliste 

Es innecesariamente difícil de comparar, si la fuente de la suma de control no contiene los dos espacios en blanco con el nombre del archivo. Eso «s de donde se originan las observaciones, pero más interesante que las muchas formas de resolver ese problema fue mi observación:

Defino una variable de control y pruebo mi función con cadenas demasiado cortas, pero coincidentes:

ok=b1eb0d822e8d841249e3d68eeb3068d3 for i in {29..32}; do md5 wp.laenderliste ${ok:1:$i} ;done fine fine fine fine 

Eso es esperado y está bien, ya que el propósito de la función es ignorar la falta de coincidencia de la «wp.laenderliste» que falta y, por lo tanto, las diferencias aún más largas .

Ahora, si agrego cosas al azar, que no coinciden, espero, por supuesto, errores, y los obtengo:

for i in {29..32}; do md5 wp.laenderliste ${ok:1:$i}GU ;done baarr baarr baarr baarr 

Como se esperaba. Pero cuando hay solo uno, el último carácter no coincidente , mira lo que sucede:

for i in {29..32}; do md5 wp.laenderliste ${ok:1:$i}G ;done fine fine fine fine 

Soy yo, sin darme cuenta de cómo se supone que funciona esto (la selección está rota), o ¿Existe realmente un error de uno por uno en la coincidencia de patrones de bash?

Las discrepancias en la mitad de la cadena importan del conteo 1:

for i in 5 9 e ; do echo md5 wp.laenderliste ${ok//$i/_} ;done md5 wp.laenderliste b1eb0d822e8d841249e3d68eeb3068d3 md5 wp.laenderliste b1eb0d822e8d84124_e3d68eeb3068d3 md5 wp.laenderliste b1_b0d822_8d841249_3d68__b3068d3 for i in 5 9 e ; do md5 wp.laenderliste ${ok//$i/_} ;done fine baarr baarr 

La versión bash:

bash -version GNU bash, Version 4.3.48(1)-release (x86_64-pc-linux-gnu) Copyright (C) 2013 Free Software Foundation, Inc. Lizenz GPLv3+: GNU GPL Version 3 oder jünger <http://gnu.org/licenses/gpl.html> 

Descargo de responsabilidad : md5sum solo es útil contra errores involuntarios, no contra ataques. No recomiendo su uso.

Y esta pregunta no es una búsqueda de mejores soluciones o soluciones alternativas. Se trata de = ~ Operador, si debe actuar como lo hace y, de ser así, por qué.

Respuesta

=~ in ([[ ]]) es una coincidencia de patrón de expresión regular (o más bien, una búsqueda , ver más abajo ). Eso «es diferente de = (o ==) que usa los mismos patrones que con los comodines de nombre de archivo.

En En particular, el asterisco en las expresiones regulares significa «cero o una copia de la unidad anterior», por lo que abc* significa ab más cero o más c s.

En su caso, el asterisco final hace que el carácter final del argumento de la función sea opcional. En su ejemplo final, el patrón se convierte en ...68d3G*, y dado que G* coincide con la cadena vacía, coincide con una cadena como ...68d3. Regexese para» cualquier cadena «es de .*, o» cualquier carácter, cualquier número de veces «.

Tenga en cuenta que la coincidencia de expresiones regulares busca una coincidencia en cualquier parte de la cadena, no «No es necesario que sea la cadena completa . Entonces, el patrón cde se encontraría en la cadena abcdefgh.

Es posible que desee usar algo como esto:

[[ "$(md5sum "$1")" = "$2 "* ]] && echo ok 

Realmente no necesitamos una coincidencia de expresión regular aquí, y dado que md5sum genera el espacio final ( más nombre de archivo) de todos modos, podemos usar eso en el patrón para verificar que coincidimos con el patrón completo. Por lo tanto, dar a la función un hash truncado no coincidiría.

Comentarios

  • Oh, ahora me siento sucio. Principalmente trabajo con sed, cuando uso la coincidencia de patrones. Por supuesto que tengo que usar. * y lo sé. De alguna manera he aprendido la idea ahora obviamente incorrecta, que tengo para olvidarse del punto en el shell, que ‘ es solo el caso para la coincidencia de nombres de archivo, ¿verdad? En el caso / esac, ¿el punto también es necesario? I ‘ ¡Me veo tan estúpido, ahora!;)
  • @userunknown, case usa los mismos patrones que con el nombre de archivo coincide, por lo que * coincide con cualquier cosa, y el punto es solo el punto. Creo que =~ es el único lugar en el shell que usa expresiones regulares. (Entonces, por supuesto, ksh / Zsh / Bash tienen globs extendidos que tienen prácticamente la misma funcionalidad que las expresiones regulares, pero con una sintaxis diferente. Sin embargo, tiene que habilitarse explícitamente en Bash).
  • También se podría hacer [ "$(md5sum < "$1")" = "$2 -" ] para eliminar la dependencia de ksh / zsh / bash (y evitar problemas con archivos cuyo nombre comience con -).
  • Ok, esa es una buena excusa. Entonces, la memoria aproximada, esa coincidencia de patrones en el caparazón es complicada, al menos era correcta. Ahora me siento mucho mejor. 🙂 Ahora probé = $2.* y esto también funciona, pero » $ 2 » * ser mejor.Pero fue solo un experimento, así que no ‘ usaré nada excepto la experiencia de aprendizaje.

Respuesta

No usaría una expresión regular aquí, solo una comparación de cadenas:

md5 () { sum=$(md5sum "$1" | awk "{print $1}") [[ $sum = "$2" ]] && echo fine || echo baarr; } 

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *