Come eliminare le righe vuote a partire dalla riga 5


10

Ho questo:

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

che sta eliminando le righe vuote e funziona bene. Come posso farlo farlo solo per le righe 5-999 (o idealmente da 5 a fine file).

Provai:

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

ma nessuno dei due ha funzionato (nessun errore).


Solo per essere sicuri: vuoi mantenere le righe da 1 a 4, indipendentemente dal fatto che siano vuote o meno, o vuoi eliminare le righe da 1 a 4, indipendentemente dal fatto che siano vuote o no? (Finora, ho assunto il primo, ma il secondo comando che hai provato mi fa meravigliare.)
Uwe,

Risposte:


12

Se si desidera eliminare tutte le righe vuote che iniziano con la riga 5 e mantenere le righe da 1 a 4, è possibile utilizzare

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

Il {è l'operatore di raggruppamento, in modo che i primi comando 5,${significa "dalla linea 5 fino alla fine dell'input ( $) eseguono i seguenti comandi finché l'abbinamento }". I comandi tra {e }possono essere nuovamente preceduti da indirizzi, quindi il comando interno /^$/dsignifica "se non c'è nulla tra inizio ( ^) e fine ( $) della riga, eliminalo". I comandi di Sed possono essere separati da ;. (Questa è una caratteristica mal documentata di sed. È supportata dalla maggior parte delle implementazioni di sed, ma non è interamente portatile .) Come notato da Hauke, il ;dopo {è facoltativo; }è necessario quello precedente .

Se si desidera eliminare tutte le righe vuote che iniziano con la riga 5 e anche eliminare le righe da 1 a 4, è più semplice:

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

Bello. Non sapevo che gli indirizzi potessero essere nidificati in quel modo. Per me funziona anche senza il comando ;.
Hauke ​​Laging,

Sì, hai ragione sul primo ;.
Uwe,

@Hauke ​​Laging È possibile separare i comandi in uno script sed da ';' mettendoli invece su linee separate. Questa è una funzione "non documentata".
Predrag Punosevac,

4

Un'altra opzione che utilizza awk:

awk 'NR<5||/./'

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

Modifica 1:

Dovrei spiegarlo, quindi ...

Questo è inutilmente complicato. Non sapevo che gli intervalli di indirizzi fossero consentiti all'interno {}. Quindi ho dovuto esprimere "elimina righe vuote" in modo diverso. Il comando principale è til modo di sed if ... then. Tsarebbe stato più semplice ma è disponibile solo per GNU sed. Cito la pagina man:

t label: se as /// ha eseguito correttamente una sostituzione dall'ultima riga di input e dall'ultimo comando t o T, quindi diramare per etichettare; se l'etichetta viene omessa, dalla fine alla fine dello script.

Abuso del famoso scomando. Non sostituisce nulla ma verifica solo se la linea è vuota. Quindi sostituisce una riga vuota con una riga vuota (potrebbe utilizzare qualsiasi cosa in sostituzione poiché la riga viene comunque eliminata).

Se sha effettuato una "sostituzione", la riga è vuota. In tal caso il comando ddeve essere eseguito. Altrimenti non si deve fare nulla. Dato tche non salta in caso di sun'azione, ho bisogno del comando branch bper saltare alla fine dello script. : labelsono obiettivi di filiale. Come gotoall'epoca oscura (quando sed è stata inventata ... te-hee).

Un'altra opzione sarebbe quella di avere s"sostituire" tutte le linee non vuote, rendendo spiù complicato il resto del comando:

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

^..*$significa "riga non vuota" e \1significa "il contenuto delle prime parentesi".


Un po 'di spiegazione per l'amor di OP (posso sentire il loro cervello cercando di strisciare fuori attraverso le orecchie la lettura di questo ...)
vonbrand
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.