Saltar al contenido

¿Cómo imprimir líneas entre dos patrones, inclusivos o exclusivos (en sed, AWK o Perl)?

Te damos la respuesta a esta contrariedad, o por lo menos eso esperamos. Si sigues con interrogantes dínoslo, que sin tardanza

Solución:

Imprimir líneas entre PAT1 y PAT2

$ awk '/PAT1/,/PAT2/' file
PAT1
3    - first block
4
PAT2
PAT1
7    - second block
PAT2
PAT1
10    - third block

O, usando variables:

awk '/PAT1/flag=1 flag; /PAT2/flag=0' file

¿Como funciona esto?

  • /PAT1/ coincide con las líneas que tienen este texto, así como /PAT2/ lo hace.
  • /PAT1/flag=1 establece el flag cuando el texto PAT1 se encuentra en una línea.
  • /PAT2/flag=0 desarma el flag cuando el texto PAT2 se encuentra en una línea.
  • flag es un patrón con la acción predeterminada, que es print $0: si flag es igual a 1 se imprime la línea. De esta forma, imprimirá todas aquellas líneas que se produzcan desde el momento PAT1 ocurre y hasta el siguiente PAT2 es visto. Esto también imprimirá las líneas de la última coincidencia de PAT1 hasta el final del archivo.

Imprimir líneas entre PAT1 y PAT2 – sin incluir PAT1 y PAT2

$ awk '/PAT1/flag=1; next /PAT2/flag=0 flag' file
3    - first block
4
7    - second block
10    - third block

Esto usa next para saltar la línea que contiene PAT1 para evitar que se imprima.

esta llamada a next se puede eliminar reorganizando los bloques: awk '/PAT2/flag=0 flag; /PAT1/flag=1' file.

Imprimir líneas entre PAT1 y PAT2 – incluyendo PAT1

$ awk '/PAT1/flag=1 /PAT2/flag=0 flag' file
PAT1
3    - first block
4
PAT1
7    - second block
PAT1
10    - third block

Mediante la colocación de flag al final, activa la acción que se configuró en PAT1 o PAT2: imprimir en PAT1, no imprimir en PAT2.

Imprimir líneas entre PAT1 y PAT2 – incluyendo PAT2

$ awk 'flag; /PAT1/flag=1 /PAT2/flag=0' file
3    - first block
4
PAT2
7    - second block
PAT2
10    - third block

Mediante la colocación de flag al principio, activa la acción que se configuró previamente y, por lo tanto, imprime el patrón de cierre pero no el de inicio.

Imprimir líneas entre PAT1 y PAT2, excluyendo líneas desde la última PAT1 hasta el final del archivo si no se produce otra PAT2

Esto se basa en una solución de Ed Morton.

awk 'flag
        if (/PAT2/)
           printf "%s", buf; flag=0; buf=""
        else
            buf = buf $0 ORS
     
     /PAT1/ flag=1' file

Como una sola línea:

$ awk 'flag if (/PAT2/)printf "%s", buf; flag=0; buf="" else buf = buf $0 ORS; /PAT1/flag=1' file
3    - first block
4
7    - second block

# note the lack of third block, since no other PAT2 happens after it

Esto mantiene todas las líneas seleccionadas en un búfer que se llena desde el momento en que se encuentra PAT1. Luego, se sigue llenando con las siguientes líneas hasta que se encuentra PAT2. En ese punto, imprime el contenido almacenado y vacía el búfer.

que tal el clasico sed ¿solución?

Imprimir líneas entre PAT1 y PAT2 – incluir PAT1 y PAT2

sed -n '/PAT1/,/PAT2/p' FILE

Imprimir líneas entre PAT1 y PAT2 – excluir PAT1 y PAT2

base de datos GNU

sed -n '/PAT1/,/PAT2//PAT1/!/PAT2/!p' FILE

Cualquier sed1

sed -n '/PAT1/,/PAT2//PAT1/!/PAT2/!p;;' FILE

o incluso (Gracias Sundeep):

base de datos GNU

sed -n '/PAT1/,/PAT2///!p' FILE

Cualquier sed

sed -n '/PAT1/,/PAT2///!p;' FILE

Imprime líneas entre PAT1 y PAT2 – incluye PAT1 pero no PAT2

Lo siguiente incluye solo el inicio del rango:

base de datos GNU

sed -n '/PAT1/,/PAT2//PAT2/!p' FILE

Cualquier sed

sed -n '/PAT1/,/PAT2//PAT2/!p;' FILE

Imprime líneas entre PAT1 y PAT2 – incluye PAT2 pero no PAT1

Lo siguiente incluye solo el final del rango:

base de datos GNU

sed -n '/PAT1/,/PAT2//PAT1/!p' FILE

Cualquier sed

sed -n '/PAT1/,/PAT2//PAT1/!p;' FILE

1 Nota sobre BSD/Mac OS X sed

Un comando como este aquí:

sed -n '/PAT1/,/PAT2//PAT1/!/PAT2/!p' FILE

Emitiría un error:

▶ sed -n '/PAT1/,/PAT2//PAT1/!/PAT2/!p' FILE
sed: 1: "/PAT1/,/PAT2/{/PAT1/!{/ ...": extra characters at the end of p command

Por esta razón, esta respuesta se ha editado para incluir versiones BSD y GNU de las frases ingeniosas.

Utilizando grep con PCRE (donde esté disponible) para imprimir marcadores y líneas entre marcadores:

$ grep -Pzo "(?s)(PAT1(.*?)(PAT2|Z))" file
PAT1
3    - first block
4
PAT2
PAT1
7    - second block
PAT2
PAT1
10    - third block
  • -P perl-regexp, PCRE. no en todos grep variantes
  • -z Trate la entrada como un conjunto de líneas, cada una terminada por un byte cero en lugar de una nueva línea
  • -o imprimir solo coincidencia
  • (?s) DotAll, es decir. dot también encuentra nuevas líneas
  • (.*?) hallazgo no codicioso
  • Z Partido solo al final de stringo antes de la nueva línea al final

Imprimir líneas entre marcadores excluyendo el marcador final:

$ grep -Pzo "(?s)(PAT1(.*?)(?=(nPAT2|Z)))" file
PAT1
3    - first block
4
PAT1
7    - second block
PAT1
10    - third block
  • (.*?)(?=(nPAT2|Z)) hallazgo no codicioso con anticipación para nPAT2 y Z

Imprimir líneas entre marcadores excluyendo marcadores:

$ grep -Pzo "(?s)((?<=PAT1n)(.*?)(?=(nPAT2|Z)))" file
3    - first block
4
7    - second block
10    - third block
  • (?<=PAT1n) mirada positiva hacia atrás para PAT1n

Imprimir líneas entre marcadores excluyendo el marcador de inicio:

$ grep -Pzo "(?s)((?<=PAT1n)(.*?)(PAT2|Z))" file
3    - first block
4
PAT2
7    - second block
PAT2
10    - third block

Si conservas alguna indecisión y forma de afinar nuestro noticia te mencionamos ejecutar un paráfrasis y con placer lo observaremos.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

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