Estoy tratando de usar sed
para eliminar textos desde la línea con el primer patrón hasta la línea con la segunda aparición del patrón final.
Por ejemplo, el primer patrón es BEGIN
y el patrón final es BREAKPOINT
.
Ejemplo de entrada:
qq ww BEGIN ab ef BREAKPOINT ij mn BREAKPOINT kk BREAKPOINT zz yy xx BEGIN ab ef BREAKPOINT ij mn BREAKPOINT pp
Rendimiento esperado:
qq ww kk BREAKPOINT zz yy xx pp
¿Podría por favor decirme cómo, o tal vez una forma alternativa de lograr esto?
PD. Solo sé cómo mostrar textos entre el primer patrón hasta la segunda aparición del patrón final, pero no sé cómo eliminarlos.
sed -n '/BEGIN/{:a;N;s/BREAKPOINT/&/2p;Ta}' file
Gracias.
Es casi seguro que no es imposible hacer esto en sed
, pero también es casi seguro que en algún lugar entre difícil e imposible entender la solución dentro de algunas semanas a menos que esté extremadamente familiarizado con sed
. Mejor entonces cambiar a un lenguaje de secuencias de comandos más legible por humanos:
awk '/^BEGIN$/ && !s { s=2 } !s /^BREAKPOINT$/ && s { s-- }' file
En resumen, la variable s
realiza un seguimiento de si hemos visto el separador inicial y, de ser así, cuántas veces queremos ver el separador final antes de volver a imprimir las líneas de entrada.
Solo con las muestras mostradas, intente seguir el código awk
, escrito y probado en GNU awk
.
awk ' /^BEGIN/,/^BREAKPOINT/{ flag=1 next } flag && /BREAKPOINT/{ flag="" next } !flag ' Input_file
Explicación: agregando una explicación detallada de lo anterior.
awk ' ##Starting awk program from here. /^BEGIN/,/^BREAKPOINT/{ ##Checking range from line starts from BEGIN till line starts BREAKPOINT then do following. flag=1 ##Setting flag to 1 here. next ##next will skip all further statements from here. } flag && /BREAKPOINT/{ ##Checking condition if flag is SET and BREAKPOINT is found then do following. flag="" ##Nullifying flag here. next ##next will skip all further statements from here. } !flag ##Checking condition if flag is NULL then print current line. ' Input_file ##Mentioning Input_file name here.
Una perla:
perl -0777 -pe 's/^BEGIN[\s\S]*?^BREAKPOINT[\s\S]*?^BREAKPOINT\R//gm' file
O,
perl -0777 -pe 's/^BEGIN(?:[\s\S]*?^BREAKPOINT\R){2}//gm' file