Realizar operaciones sed en números de línea dados

8

Me pregunto si hay una manera simple de operar en ciertas líneas con números de línea preasignados.

Digamos que quiero generar las líneas 1, 7, 14 y 16 de un archivo, simplemente puedo hacer

sed -n '1p;7p;14p;16p' input_file

pero esto se vuelve más complicado cuando la operación no es solo imprimir, y no quiero escribir el mismo comando largo 4 veces (y sí, sé que puedo construir este comando sed largo sustituyendo la misma variable bash 4 veces, pero eso no es lo suficientemente ideal ...), es decir

sed -n '1{long_command};7{long_command};14{long_command};16{long_command}' input_file

¿Hay alguna manera de hacer la operación en estas líneas específicas de mi archivo? Estoy esperando algo como

sed -n '1,7,14,16p'

que ciertamente no funcionará en la forma actual.

Cualquier ayuda será apreciada. "No, no es posible." con explicaciones es también una respuesta que aceptaré.

Weijun Zhou
fuente
Es fácil conawk
RomanPerekhrest

Respuestas:

11

Puedes usar ramas:

sed '
  1b1
  7b1
  14b1
  16b1

  # for the rest to be left alone, branch off (or delete them with "d"):
  b

  :1
  long_command'

(tenga en cuenta que también puede agregar algunos 20,25b1rangos de línea o /re/b1incluir líneas que coincidan con re).

O podrías usar awk:

awk 'NR == 1 || NR == 7 || ... {stuff}'

O usando un hash:

awk -v l=1,7,14,16 '
  BEGIN{split(l, a, ","); for (i in a) lines[a[i]]}

  NR in lines {stuff}'

(o BEGIN{lines[1]lines[7]lines[14]lines[16]}si no hay demasiados)

Stéphane Chazelas
fuente
Gracias, nunca pensé en ramas ... Simplemente parece ser la herramienta ideal para usar en este caso.
Weijun Zhou
¿Cómo utilizar ramas como esta en sed con un patrón de búsqueda? como decir que quiero emparejar o eliminar un patrón después de la enésima línea?
qodeninja
3

Simplemente invierta su selección y elimínela:

sed '2,6d;8,13d;15d;17,$d;long_command'
Philippos
fuente
Esta también es una buena solución, aunque un poco más difícil para manejar números de línea que se leen desde la entrada estándar, por ejemplo.
Weijun Zhou
1

Primera variante:

Puedes usar este truco:

sed -nf <(printf '%dp\n' 1 7 14 16)

-f script-file : agrega el contenido del script-file a los comandos que se ejecutarán.

Pruebas

seq 1 20 | sed -nf <(printf '%dp\n' 1 7 14 16)

Salida

1
7
14
16

Segunda variante:

Al principio, el auxiliar sedse usa para filtrar solo las líneas necesarias del archivo, luego estas líneas se canalizan a la principal sedcon el comando largo.

sed -n '1p; 7p; 14p; 16p' input.txt | sed 'long command'
MiniMax
fuente