/ / AWK coincidencia de patrón Regex - expresiones regulares, awk

Coincidencia de patrón AWG Regex - regex, awk

Tengo un archivo de texto, y necesito identificar un cierto patrón en un campo. Estoy usando AWK e intento usar la función match ().

El requisito es que necesito ver si el siguiente patrón existe en una cadena de dígitos

??????1?
??????3?
??????5?
??????7?

es decir, solo me interesa que el último dígito sea un 1, 3, 5 o un 7.

Tengo una solución, que se ve así;

    b = match($23, "[0-9][0-9][0-9][0-9][0-9][0-9]1[0-9]")
c = match($23, "[0-9][0-9][0-9][0-9][0-9][0-9]3[0-9]")
d = match($23, "[0-9][0-9][0-9][0-9][0-9][0-9]5[0-9]")
e = match($23, "[0-9][0-9][0-9][0-9][0-9][0-9]7[0-9]")

if (b || c || d || e)
{
print "Found a match" $23
}

Aunque creo que debería poder escribir la expresión regular de forma más sucinta como esta;

b = match($23, "[0-9]{6}1[0-9]")

Pero esto no funciona.

¿Me estoy perdiendo algo, o mis habilidades de expresión regular (que no son geniales) realmente son tan malas?

Gracias de antemano

Respuestas

3 para la respuesta № 1

El delimitador de expresiones regulares es /.../no "...". Cuando usas comillas en un contexto RE, eresdiciendo awk que hay un RE almacenado dentro de un literal de cadena y ese literal de cadena se analiza dos veces, una vez cuando se lee el script y luego otra vez cuando se ejecuta, lo que hace su especificación mucho más complicada para acomodar ese doble análisis.

Entonces, no escribas:

b = match($23, "[0-9]{6}1[0-9]")

escribir:

b = match($23, /[0-9]{6}1[0-9]/)

en lugar.

Sin embargo, ese no es su problema. El problema más probable que tiene es que está llamando a una versión de awk que no admite intervalos RE como {6}. Si está utilizando una versión anterior de GNU awk, puede habilitar esa funcionalidad agregando el --re-interval bandera:

awk --re-interval "...b = match($23, /[0-9]{6}1[0-9]/)..."

pero si es eso o si está usando un awk que simplemente no admite RE_intervals, lo mejor que puede hacer es obtener una versión más nueva de gawk.

Finalmente, todo el script se puede reducir a:

awk --re-interval "$23 ~ /[0-9]{6}[1357][0-9]/{print "Found a match", $23}"

Cambio [0-9] a [[:digit:]] para independencia regional si lo desea.

La razón por la cual los intervalos de RE no fueron soportados por defecto en gawk hasta hace poco es que el viejo awk no los soportaba por lo que un script que tenía un RE de a{2}b cuando se ejecuta en viejo awk habría estado buscandoporque literalmente esos 5 chars y gawk no querían que los viejos scripts se rompieran silenciosamente cuando se ejecutaban en gawk en lugar de old awk. Algunos liberan a los gawk con razón decidieron dar el paso y habilitar los intervalos de RE por defecto para nuestra conveniencia de la compatibilidad con versiones anteriores .


0 para la respuesta № 2

Aqui hay uno awk solución:

awk -v FS="" "$7~/(1|3|5|7)/" file

Configurando FS a nada, cada personaje se convierte en un campo. Entonces podemos probar el campo # 7.

Como Tom publicó.

awk -v FS="" "$7~/[1357]/" file