Coincidencia de expresiones regulares de múltiples líneas en AWK. && operador?

No estoy seguro si el operador de && trabaja en expresiones regulares. Lo que estoy tratando de hacer es hacer coincidir una línea de manera que comience con un número y tenga la letra ‘a’ Y la siguiente línea comience con un número y tenga la letra ‘b’ Y la siguiente línea … letra ‘c’ . Esta secuencia abc se utilizará como un identificador único para comenzar a leer el archivo.

Esto es lo que estoy buscando en awk.

/(^[0-9]+ .*a)&&\n(^[0-9]+ .*b)&&\n(^[0-9]+ .*c) { print $0 } 

Solo una de estas expresiones regulares funciona como (^ [0-9] +. * A), pero no estoy seguro de cómo unirlas con Y LA PRÓXIMA LÍNEA ES ESTA.

Mi archivo sería como:

 JUNK UP HERE NOT STARTING WITH NUMBER 1 a 0.110 0.069 2 a 0.062 0.088 3 a 0.062 0.121 4 b 0.062 0.121 5 c 0.032 0.100 6 d 0.032 0.100 7 e 0.032 0.100 

Y lo que quiero es:

 3 a 0.062 0.121 4 b 0.062 0.121 5 c 0.032 0.100 6 d 0.032 0.100 7 e 0.032 0.100 

[Actualización basada en aclaraciones.]

Un bit de alto orden es que Awk es un lenguaje orientado a líneas, por lo que no podrá hacer una coincidencia de patrón normal para abarcar líneas. La forma habitual de hacer algo como esto es hacer coincidir cada línea por separado, y hacer que una cláusula / statement posterior resuelva si todas las piezas correctas se han combinado.

Lo que estoy haciendo aquí es buscar una a en el segundo campo en una línea, una b en el segundo campo en otra línea y una c en el segundo campo en una tercera línea. En los dos primeros casos, guardo el contenido de la línea y el número de línea en la que ocurrió. Cuando la tercera línea coincide y aún no hemos encontrado la secuencia completa, retrocedo y verifico si las otras dos líneas están presentes y con números de línea aceptables. Si todo está bien, imprimo las líneas anteriores almacenadas en búfer y configuro un indicador que indica que todo lo demás debería imprimir.

Aquí está el guión:

 $2 == "a" { a = $0; aLine = NR; } $2 == "b" { b = $0; bLine = NR; } $2 == "c" && !keepPrinting { if ((bLine == (NR - 1)) && (aLine == (NR - 2))) { print a; print b; keepPrinting = 1; } } keepPrinting { print; } 

Y aquí hay un archivo con el que lo probé:

 JUNK UP HERE NOT STARTING WITH NUMBER 1 a 0.110 0.069 2 a 0.062 0.088 3 a 0.062 0.121 4 b 0.062 0.121 5 c 0.032 0.100 6 d 0.032 0.100 7 e 0.032 0.100 8 a 0.099 0.121 9 b 0.098 0.121 10 c 0.097 0.100 11 x 0.000 0.200 

Esto es lo que obtengo cuando lo ejecuto:

 $ awk -f blort.awk blort.txt 3 a 0.062 0.121 4 b 0.062 0.121 5 c 0.032 0.100 6 d 0.032 0.100 7 e 0.032 0.100 8 a 0.099 0.121 9 b 0.098 0.121 10 c 0.097 0.100 11 x 0.000 0.200 

No, no funciona. Podrías probar algo como esto:

 /(^[0-9]+.*a[^\n]*)\n([0-9]+.*b[^\n]*)\n([0-9]+.*c[^\n]*)/ 

Y repítelo para tantas letras como necesites.

El [^\n]* coincidirá con la mayor cantidad posible de caracteres que no sean de rotura de línea (así que hasta la línea de línea).

Estoy tratando de hacer esto en python. Al hacer un iterador fuera de las líneas, y tratar de hacer coincidir las siguientes dos líneas con next ().

 lines = iter([line for line in open("FILE").readlines() if re.match(r'^([0-9])',line)]) for line in lines: count = 50 if line.find('a'): if next(lines).find('b'): if next(lines).find('c'): while count > 0: print line count -=1 

Pero simplemente no está funcionando bien. Lo ideal sería encontrar esa coincidencia e imprimir las siguientes 50 líneas a partir de esa ‘a’. Tal vez necesito implementar algún tipo de máquina de estado.

Un amigo me escribió este progtwig awk. Es una máquina de estado. Y funciona.

 #!/usr/bin/awk -f BEGIN { # We start out in the "idle" state. state = "idle" } /^[0-9]+[[:space:]]+q/ { # Everytime we encounter a "# q" we either print it or go to the # "q_found" state. if (state != "printing") { state = "q_found" line_q = $0 } } /^[0-9]+[[:space:]]+r/ { # If we are in the q_found state and "# r" immediate follows, # advance to the r_found state. Else, return to "idle" and # wait for the "# q" to start us off. if (state == "q_found") { state = "r_found" line_r = $0 } else if (state != "printing") { state = "idle" } } /^[0-9]+[[:space:]]+l/ { # If we are in the r_found state and "# l" immediate follows, # advance to the l_found state. Else, return to "idle" and # wait for the "# q" to start us off. if (state == "r_found") { state = "l_found" line_l = $0 } else if (state != "printing") { state = "idle" } } /^[0-9]+[[:space:]]+i/ { # If we are in the l_found state and "# i" immediate follows, # we're ready to start printing. First, display the lines we # squirrelled away then move to the "printing" state. Else, # go to "idle" and wait for the "# q" to start us off. if (state == "l_found") { state = "printing" print line_q print line_r print line_l line = 0 } else if (state != "printing") { state = "idle" } } /^[0-9]+[[:space:]]+/ { # If in state "printing", print 50 lines then stop printing if (state == "printing") { if (++line < 48) print } }