Tengo un archivo como el siguiente y me gustaría imprimir las líneas entre dos patrones de PAT1
y PAT2
.
1
2
PAT1
3 - first block
4
PAT2
5
6
PAT1
7 - second block
PAT2
8
9
PAT1
10 - third block
He leído Cómo seleccionar las líneas entre dos marcador de patrones que puede ocurrir varias veces con awk/sed pero tengo curiosidad para ver todas las posibles combinaciones de este, incluyendo o excluyendo el patrón.
¿Cómo puedo imprimir todas las líneas entre dos patrones?
- Estoy publicando un intento de la canónica de respuesta a la ¿Cómo seleccionar las líneas entre dos marcador de patrones que puede ocurrir varias veces con awk/sed, de forma que se cubren todos los casos. Sigo está bien Preguntar y Responder a Sus Propias Preguntas y publicado la respuesta de la Comunidad Wiki, así que siéntase libre para mejorarlo!
- sí, gracias! También comprobé esto antes de seguir adelante y publicar esta pregunta/respuesta. El punto aquí es proporcionar un conjunto de herramientas de este, ya que el volumen de comentarios (y los votos) en mi otra respuesta me llevan a pensar que un genérico post sería de buena ayuda para los lectores futuros.
- Véase también thelinuxrain.com/articles/how-to-use-flags-in-awk
- No tenía noticias así que me decidí a tener un ir en la mejora de la pregunta para posicionarse mejor en Google y aclarar lo que el alcance es. Siéntase libre de volver si no estás contento con él.
- no está seguro de que mis comentarios eran de esperar, pero en cualquier caso gracias por la edición! Se ve bien para mí. Gracias por tomarse el tiempo en esto
Imprimir líneas entre PAT1 y PAT2
O, utilizando las variables:
¿Cómo funciona esto?
/PAT1/
coincide con las líneas de tener este texto, así como/PAT2/
hace./PAT1/{flag=1}
establece elflag
cuando el textoPAT1
se encuentra en una línea./PAT2/{flag=0}
desactiva elflag
cuando el textoPAT2
se encuentra en una línea.flag
es un patrón con la acción por defecto, que esprint $0
: siflag
es igual a 1 se imprime la línea. De esta manera, se imprimirá todas esas líneas que se producen desde el momento en quePAT1
se produce y hasta la próximaPAT2
es visto. Esto también imprimir las líneas desde el último partido dePAT1
hasta el final del archivo.Imprimir líneas entre PAT1 y PAT2 – no incluyendo PAT1 y PAT2
Este utiliza
next
a pasar la línea que contienePAT1
con el fin de evitar este impreso.Esta llamada a
next
puede ser disminuido por la redistribución de los bloques:awk '/PAT2/{flag=0} flag; /PAT1/{flag=1}' file
.Imprimir líneas entre PAT1 y PAT2 – incluyendo PAT1
Mediante la colocación de
flag
al final, se desencadena la acción que se establece en PAT1 o PAT2: para imprimir en PAT1, no para imprimir en PAT2.Imprimir líneas entre PAT1 y PAT2 – incluyendo PAT2
Mediante la colocación de
flag
al principio, se desencadena la acción que se establece previamente y, por tanto, imprimir el patrón de cierre, pero no la partida.Imprimir líneas entre PAT1 y PAT2 – excluyendo las líneas de la última PAT1 para el final del archivo si no hay otros PAT2 se produce
Esto se basa en un solución Ed Morton.
Como un one-liner:
Esto mantiene todas las líneas seleccionadas en un búfer que rellena desde el momento en que PAT1 se encuentra. Entonces, sigue siendo llenado con las siguientes líneas hasta PAT2 se encuentra. En ese punto, se imprime el contenido almacenado y se vacía el búfer.
Lo que el clásico
sed
solución?Imprimir líneas entre PAT1 y PAT2 – incluir PAT1 y PAT2
Imprimir líneas entre PAT1 y PAT2 – excluir PAT1 y PAT2
GNU sed
Cualquier sed1
o incluso (Gracias Sundeep):
GNU sed
Cualquier sed
Imprimir líneas entre PAT1 y PAT2 – incluir PAT1 pero no PAT2
El siguiente incluye sólo el rango de inicio:
GNU sed
Cualquier sed
Imprimir líneas entre PAT1 y PAT2 – incluir PAT2 pero no PAT1
El siguiente incluye sólo el rango final:
GNU sed
Cualquier sed
1 Nota sobre BSD, Mac OS X, sed
Un comando como este aquí:
Que emiten un error:
Por esta razón, esta respuesta ha sido editada para incluir BSD y GNU versiones de la uno-trazadores de líneas.
sed -n '/PAT1/,/PAT2/{//!p}' file
… de manualempty regular expression ‘//’ repeats the last regular expression match
If an RE is empty (that is, no pattern is specified) sed shall behave as if the last RE used in the last command applied (either as an address or as part of a substitute command) was specified.
se Ve como la única pregunta que queda aquí es cómo interpretarthe last RE
. BSD está diciendo algo a esto. Mira aquí (Punto 23): github.com/freebsd/freebsd/blob/master/usr.bin/sed/POSIX/PAT1/,/PAT2/{//!p}
sólo funcionará si la última RE es dinámico.. si era estático,//
se resuelve a/PAT2/
Utilizando
grep
con PCRE (donde esté disponible) para imprimir los marcadores y las líneas entre los marcadores:-P
perl-regexp, PCRE. No en todos losgrep
variantes-z
Tratar la entrada como un conjunto de líneas, cada una de lasterminada por un byte cero en lugar de un salto de línea
-o
imprimir sólo la coincidencia de(?s)
DotAll, es decir. dot encuentra saltos de línea, así(.*?)
nongreedy encontrar\Z
Partido sólo al final de la cadena, o antes de nueva línea al finalImprimir líneas entre los marcadores excluyendo marcador final:
(.*?)(?=(\nPAT2|\Z))
nongreedy encontrar con lookahead para\nPAT2
y\Z
Imprimir líneas entre los marcadores excluyendo los marcadores:
(?<=PAT1\n)
positivo lookbehind paraPAT1\n
Imprimir líneas entre los marcadores excluyendo el marcador de inicio:
Aquí es otro enfoque
Incluir ambos patrones (por defecto)
Máscara de ambos patrones
Máscara patrón de inicio
Máscara final patrón
Usted puede hacer lo que quiera con
sed
por la supresión de la normal de impresión de patrón de espacio con-n
. Por ejemplo, para incluyen los patrones en el resultado que usted puede hacer:A excluir los patrones y acaba de imprimir lo que hay entre ellas:
Que se descompone como
sed -n '/PAT1/,/PAT2/
– localizar el intervalo entrePAT1
yPAT2
y suprimir la impresión;/PAT1/{n};
– si coincide conPAT1
mover an
(siguiente) línea;/PAT2/{d};
– si coincide conPAT2
borrar línea;p
– imprimir todas las líneas que caen dentro de/PAT1/,/PAT2/
y no fueron omitidos o eliminado.sed
solución.Alternativamente:
Esto borra todas las líneas, excepto para aquellos entre e incluyendo el INICIO y el FINAL, entonces la
//d
elimina el INICIO y el FINAL de las líneas desde//
causas sed para el uso de los patrones previos.Para la integridad, aquí es un Perl solución:
Imprimir líneas entre PAT1 y PAT2 – incluir PAT1 y PAT2
o:
Imprimir líneas entre PAT1 y PAT2 – excluir PAT1 y PAT2
o:
Imprimir líneas entre PAT1 y PAT2 – excluir PAT1 sólo
Imprimir líneas entre PAT1 y PAT2 – excluir PAT2 sólo
Ver también:
perldoc perlop
para más información sobre el/PAT1/../PAT2/
gramática:Para la
-n
opción, consulteperldoc perlrun
, lo que hace que Perl se comportan comosed -n
.Perl Libro De Cocina, 6.8 para una discusión detallada de la extracción de un intervalo de líneas.