sed o awk: elimina n líneas siguiendo un patrón

¿Cómo mezclaría patrones y rangos numéricos en sed (o cualquier herramienta similar, awk, por ejemplo)? Lo que quiero hacer es hacer coincidir ciertas líneas en un archivo y eliminar las siguientes n líneas antes de continuar, y quiero hacerlo como parte de una canalización.

Voy a probar esto.

Para eliminar 5 líneas después de un patrón (incluida la línea con el patrón):

sed -e '/pattern/,+5d' file.txt 

Para borrar 5 líneas después de un patrón (excluyendo la línea con el patrón):

 sed -e '/pattern/{n;N;N;N;N;d}' file.txt 

Soluciones simples awk :

Suponga que la expresión regular a usar para encontrar líneas que coincidan se almacena en la variable de shell $regex y el recuento de líneas para omitir en $count .

Si la línea coincidente también debe omitirse ( $count + 1 líneas se omiten):

 ... | awk -v regex="$regex" -v count="$count" \ '$0 ~ regex { skip=count; next } --skip >= 0 { next } 1' 

Si la línea coincidente no se debe omitir (líneas $count después de que se salte la coincidencia):

 ... | awk -v regex="$regex" -v count="$count" \ '$0 ~ regex { skip=count; print; next } --skip >= 0 { next } 1' 

Explicación:

  • -v regex="$regex" -v count="$count" define las variables awk función de las variables del mismo nombre.
  • $0 ~ regex coincide con la línea de interés
    • { skip=count; next } { skip=count; next } inicializa el conteo de saltos y avanza a la línea siguiente, salteando efectivamente la línea correspondiente; en la segunda solución, la print anterior garantiza que no se omita.
    • --skip >= 0 disminuye el conteo de saltos y toma medidas si es (aún)> = 0, lo que implica que la línea en cuestión se debe omitir.
    • { next } pasa a la siguiente línea, salteando efectivamente la línea actual
  • 1 es una abreviatura de uso común para { print } ; es decir, la línea actual simplemente se imprime
    • Solo las líneas que no coinciden y que no saltan llegan a este comando.
    • La razón por la cual 1 es equivalente a { print } es que 1 se interpreta como un patrón booleano que, por definición, siempre se evalúa como verdadero, lo que significa que su acción asociada (bloque) se ejecuta incondicionalmente. Como no hay acción asociada en este caso, awk predetermina a imprimir la línea.

Esta solución le permite pasar “n” como parámetro y leerá sus patrones desde un archivo:

 awk -vn=5 ' NR == FNR {pattern[$0]; next} { for (patt in pattern) { if ($0 ~ patt) { print # remove if you want to exclude a matched line for (i=0; i 

El archivo llamado "-" significa stdin para awk, por lo que es adecuado para su canalización

Esto podría funcionar para usted:

 cat < pattern_number.txt > 5 3 > 10 1 > 15 5 > ! sed 's|\(\S*\) \(\S*\)|/\1/,+\2{//!d}|' pattern_number.txt | sed -f - < (seq 21) 1 2 3 4 5 9 10 12 13 14 15 21