Cómo eliminar líneas en blanco a partir de la línea 5


10

Tengo esto:

sed -i '/^$/d' temp_spec.rb

que está eliminando líneas en blanco y funciona bien. ¿Cómo puedo hacer que solo haga esto para las líneas 5-999 (o idealmente 5 para el final del archivo)?

Lo intenté:

sed -n5,999 -i '/^$/d' temp_spec.rb
sed '5,999!d/^$/d' temp_spec.rb

pero ninguno funcionó (sin errores).


Solo para estar seguro: ¿Desea mantener las líneas 1 a 4, sin importar si están en blanco o no, o desea eliminar las líneas 1 a 4, sin importar si están en blanco o no? (Hasta ahora, asumí el primero, pero el segundo comando que probaste me hace preguntarme)
Uwe

Respuestas:


12

Si desea eliminar todas las líneas en blanco que comienzan con la línea 5 y mantener las líneas 1 a 4, puede usar

sed -i '5,${;/^$/d;}' temp_spec.rb

El {es el operador de agrupación, por lo que el primer comando 5,${significa "desde la línea 5 hasta el final de input ( $) ejecuta los siguientes comandos hasta la coincidencia }". Los comandos entre {y }pueden ser prefijados nuevamente por direcciones, por lo que el comando interno /^$/dsignifica "si no hay nada entre el principio ( ^) y el final ( $) de la línea, elimínelo". Los comandos Sed se pueden separar por ;. (Esta es una característica mal documentada de sed. Es compatible con la mayoría de las implementaciones de sed, pero no es completamente portátil ). Como señaló Hauke, el ;after {es opcional; el anterior }se requiere, sin embargo.

Si desea eliminar todas las líneas en blanco que comienzan con la línea 5 y también eliminar las líneas 1 a 4, es más fácil:

sed -i '1,4d;/^$/d' temp_spec.rb

Agradable. No sabía que las direcciones se pueden anidar de esa manera. Para mí también funciona sin el liderazgo ;.
Hauke ​​Laging

Sí, tienes razón sobre lo primero ;.
Uwe

@Hauke ​​Laging Puede separar los comandos en un script sed por ';' en lugar de ponerlos en las líneas separadas. Esa es una característica "indocumentada".
Predrag Punosevac

4

Otra opción con awk:

awk 'NR<5||/./'

2
sed '5,${s/^$//; t delete; b end; : delete; d; : end;}' temp_spec.rb

Editar 1:

Se supone que debo explicar esto, así ...

Esto es innecesariamente complicado. No sabía que los rangos de direcciones están permitidos dentro {}. Así que tuve que expresar "eliminar líneas vacías" de manera diferente. El comando central es tcuál es la forma de sed if ... then. Thubiera sido más fácil pero está disponible solo para GNU sed. Cito la página del manual:

etiqueta t: si as /// ha realizado una sustitución exitosa desde que se leyó la última línea de entrada y desde el último comando t o T, entonces bifurca a etiqueta; Si se omite la etiqueta, bifurca hasta el final del guión.

Abuso del famoso scomando. No reemplazará nada, solo probará si la línea está vacía. Por lo tanto, reemplaza una línea vacía por una línea vacía (podría usar cualquier cosa como reemplazo ya que la línea se elimina de todos modos).

Si sha hecho un "reemplazo", entonces la línea está vacía. En ese caso dse ejecutará el comando . De lo contrario, no se debe hacer nada. Como tno salta en caso de una sacción, necesito el comando de bifurcación bpara saltar al final del guión. : labelson objetivos de sucursal. Como en gotoaquel entonces en la edad oscura (cuando se inventó sed ... te-hee).

Otra opción sería tener s"reemplazar" todas las líneas no vacías, haciendo smás fácil el resto del comando pero más complicado:

sed '5,${s/^\(..*\)$/\1/; t end; d; : end;}' input

^..*$significa "línea no vacía" y \1significa "el contenido de los primeros corchetes".


Un poco de explicación por el bien de OP (puedo sentir su cerebro tratando de arrastrarse por los oídos leyendo esto ...)
vonbrand
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.