Elimina le righe vuote usando sed


350

Sto cercando di eliminare le righe vuote utilizzando sed:

sed '/^$/d'

ma non ho fortuna.

Ad esempio, ho queste righe:

xxxxxx


yyyyyy


zzzzzz

e voglio che sia come:

xxxxxx
yyyyyy
zzzzzz

Quale dovrebbe essere il codice per questo?


2
il tuo comando sed sembra a posto, dovrebbe funzionare
perreal

Il comando sopra non funzionerebbe anche se non si dispone di uno spazio / scheda ma terminazioni di riga CR + LF .
Devnull

Risposte:


628

Potresti avere spazi o tab nella riga "vuota". Utilizzare le classi POSIX con sedper rimuovere tutte le righe contenenti solo spazi bianchi:

sed '/^[[:space:]]*$/d'

Una versione più breve che utilizza ERE, ad esempio con gnu sed:

sed -r '/^\s*$/d'

(Notare che sed NON supporta PCRE.)


3
@HuStmpHrrr gnu sed non supporta affatto PCRE. è ERE con-r
Kent,

8
OS X necessario sed -i "" '/^[[:space:]]*$/d' <filename>,
jww

@BernieReiter ^\s*$corrisponderà a tutte le righe "vuote", vuol dire che qui la riga non contiene caratteri o la riga contiene solo stringhe vuote (ad es. Spazi). Tutte le linee abbinate verranno rimosse da sed, con il dcomando.
Kent,

96

Mi manca la awksoluzione:

awk 'NF' file

Che ritornerebbe:

xxxxxx
yyyyyy
zzzzzz

Come funziona? Dato che NFsta per "numero di campi", quelle righe vuote hanno 0 fiedls, quindi awk valuta 0 come False e nessuna linea viene stampata; tuttavia, se esiste almeno un campo, la valutazione è True e fa awkeseguire la sua azione predefinita: stampare la riga corrente.


1
Whoah. Funziona anche con la versione "minimizzata" di awk di BSD (versione 20121220 (FreeBSD). Grazie :-)
Bernie Reiter,

@BernieReiter sei il benvenuto :) Sì, questa è una cosa idiomatica di base che tutte le versioni di awk consentono.
fedorqui "SO smette di danneggiare" il

Ed è molto più veloce anche se - per un test rapido e sporco - sto invocando due volte awk: $ time (topic companies <data.tpx | awk 'NF' - | awk -f dialog_menu.awk -) real 0m0.006s user 0m0.000s sys 0m0.008s $ time (topic companies <data.tpx | gsed '/^\s*$/d' | awk -f dialog_menu.awk -) real 0m0.014s user 0m0.002s sys 0m0.006s sapresti un modo ingegnoso di includerlo in uno script awk come, ad esempio, un modello? awk '/ mypattern / {do stuff ...}'
Bernie Reiter,

@BernieReiter puoi dire awk 'NF {do stuff...}'.
fedorqui "SO smettere di danneggiare" il

1
Nota che questo ignorerà anche le linee solo con spazi bianchi.
Wisbucky,

60

sed '/^$/d'dovrebbe andare bene, ti aspetti di modificare il file in atto? In tal caso, dovresti usare la -ibandiera.

Forse quelle linee non sono vuote, quindi in questo caso, guarda questa domanda Rimuovi le righe vuote dai file txt, rimuovi gli spazi dall'inizio e dalla fine della linea Credo che sia quello che stai cercando di ottenere.


sì. sto modificando un file. * .csv. come dovrebbe essere posizionato -i al comando sed?
jonas,

2
sed -i '/^$/d'è un modo per farlo.
Alberto Zaccagni,

49

1
Questi vengono visualizzati correttamente nel tuo strumento online, ma non[] devono essere esclusi in un'espressione di parentesi, quindi il codice qui non è corretto per \[\[:space:\]\]o \[ \t\]- dovrebbe essere [[:space:]]e [ \t].
Benjamin W.

1
@BenjaminW. Grazie per averlo colto. Quelli non provenivano dall'autore originale, ma provenivano da Modifica 3 quando fu cambiato da testo normale a "codice", che poi "espose" l'escape `\`. Li ho riparati ora.
Wisbucky,

30

Credo che questo sia il più semplice e veloce:

cat file.txt | grep .

Se è necessario ignorare anche tutte le righe degli spazi bianchi, provare questo:

cat file.txt | grep '\S'

Esempio:

s="\
\
a\
 b\
\
Below is TAB:\
    \
Below is space:\
 \
c\
\
"; echo "$s" | grep . | wc -l; echo "$s" | grep '\S' | wc -l

uscite

7
5

5
Non catgrepgrep . file.txt
ce n'è

3
Sì, lo so, ma la domanda iniziale non menzionava se l'origine è un file o qualcos'altro, quindi la soluzione è ciò che viene dopo "|" e prima solo un esempio di origine. Semplicemente per distinguere la soluzione dalla fonte delle linee.
Vadim,

2
grep '\S'non è sicuramente portatile. In tal caso, grep -Pè possibile utilizzare grep -P '\S'ma non è supportato su tutte le piattaforme.
triplo il

L'aspetto negativo di grep .rispetto alle altre soluzioni è che metterà in evidenza tutto il testo in rosso. Le altre soluzioni possono preservare i colori originali. Confronta unbuffer apt search foo | grep .conunbuffer apt search foo | grep -v ^$
wisbucky

15

Con l'aiuto della risposta accettata qui e della risposta accettata sopra, ho usato:

$ sed 's/^ *//; s/ *$//; /^$/d; /^\s*$/d' file.txt > output.txt

`s/^ *//`  => left trim
`s/ *$//`  => right trim
`/^$/d`    => remove empty line
`/^\s*$/d` => delete lines which may contain white space

Questo copre tutte le basi e funziona perfettamente per le mie esigenze. Complimenti per i poster originali @Kent e @kev


5

Si può dire:

sed -n '/ / p' filename    #there is a space between '//'

.. il che significa che stai print all lines except the empty one(s)zitto
Timo

2

Puoi fare qualcosa del genere anche usando "grep":

egrep -v "^$" file.txt


2

Molto probabilmente stai vedendo il comportamento imprevisto perché il tuo file di testo è stato creato su Windows, quindi la sequenza di fine riga è \r\n. È possibile utilizzare dos2unix per convertirlo in un file di testo in stile UNIX prima di eseguire sed o utilizzare

sed -r "/^\r?$/d"

per rimuovere le righe vuote indipendentemente dalla presenza del ritorno a capo.


Ciao, cosa sta -rfacendo la bandiera ed è possibile combinarlo con -iper modificare direttamente il file ed evitare di stampare sullo schermo. Inoltre, penso che questo comando funzionerebbe anche comesed -r "/^\r$/d"
Alexander Cska,

2

Un'altra opzione, senza sed, awk, perl, ecc

strings $file > $output

stringhe: stampa le stringhe di caratteri stampabili nei file.


Vuoi dire strings invece string?
Mickael B.

Ciao @MickaelB. Hai ragione, lo aggiusto.
user319660

0

La mia bashrisposta specifica è raccomandare di utilizzare l' perloperatore di sostituzione con il gflag di modello globale per questo, come segue:

$ perl -pe s'/^\n|^[\ ]*\n//g' $file
xxxxxx
yyyyyy
zzzzzz

Questa risposta illustra la contabilità se le righe vuote contengono o meno spazi ( [\ ]*), oltre a utilizzare |per separare più termini / campi di ricerca. Testato su macOS High Sierra e CentOS 6/7.

Cordiali saluti, il codice originale dell'OP sed '/^$/d' $filefunziona perfettamente in bashTerminal su macOS High Sierra e CentOS 6/7 Linux in un cluster supercomputer ad alte prestazioni.


-3

Per me con FreeBSD 10.1 con sed funzionato solo questa soluzione:

sed -e '/^[     ]*$/d' "testfile"

all'interno []ci sono simboli di spazio e tabulazione.

il file di test contiene:

fffffff next 1 tabline ffffffffffff

ffffffff next 1 Space line ffffffffffff

ffffffff empty 1 lines ffffffffffff

============ EOF =============
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.