Löschen Sie leere Zeilen mit sed

349

Ich versuche leere Zeilen mit sed zu löschen:

sed '/^$/d'

aber ich habe kein Glück damit.

Zum Beispiel habe ich diese Zeilen:

xxxxxx


yyyyyy


zzzzzz

und ich möchte, dass es so ist:

xxxxxx
yyyyyy
zzzzzz

Was sollte der Code dafür sein?

Jonas
quelle
2
Ihr sed Befehl sieht gut aus, es sollte funktionieren
perreal
Der obige Befehl würde nicht funktionieren, selbst wenn Sie kein Leerzeichen / Tabulator, sondern CR + LF-Zeilenenden haben .
devnull
1
Informationen zu awk finden Sie unter: Entfernen von Leerzeilen in awk oder Verwenden von grep im Allgemeinen unter: Entfernen von Leerzeilen aus einer Datei in der Shell?
Kenorb

Antworten:

627

Möglicherweise befinden sich Leerzeichen oder Tabulatoren in Ihrer "leeren" Zeile. Verwenden Sie POSIX-Klassen mit sed, um alle Zeilen zu entfernen, die nur Leerzeichen enthalten:

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

Eine kürzere Version, die ERE verwendet, zum Beispiel mit gnu sed:

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

(Beachten Sie, dass sed PCRE NICHT unterstützt.)

Kent
quelle
3
@HuStmpHrrr gnu sed unterstützt PCRE überhaupt nicht. es ist ERE mit-r
Kent
8
OS X benötigt sed -i "" '/^[[:space:]]*$/d' <filename>,
jww
@BernieReiter stimmt ^\s*$mit allen "leeren" Zeilen überein. Leer bedeutet hier, dass die Zeile keine Zeichen enthält oder dass die Zeile nur leere Zeichenfolgen enthält (z. B. Leerzeichen). Alle übereinstimmenden Zeilen werden mit dem dBefehl von sed entfernt .
Kent
96

Mir fehlt die awkLösung:

awk 'NF' file

Welches würde zurückkehren:

xxxxxx
yyyyyy
zzzzzz

Wie funktioniert das? Da NFfür "Anzahl der Felder" steht, haben diese leeren Zeilen 0 fiedls, so dass awk 0 zu False auswertet und keine Zeile gedruckt wird; Wenn jedoch mindestens ein Feld vorhanden ist, lautet die Auswertung True und führt awkdie Standardaktion aus: Drucken Sie die aktuelle Zeile.

fedorqui 'SO hör auf zu schaden'
quelle
1
Whoah. Läuft sogar mit BSDs "minimierter" Version von awk (Version 20121220 (FreeBSD). Danke :-)
Bernie Reiter
@BernieReiter du bist willkommen :) Ja, das ist eine sehr grundlegende Redewendung, die alle awk-Versionen erlauben.
Fedorqui 'SO hör auf zu schaden'
Und es ist so viel schneller, obwohl ich - für einen schnellen und schmutzigen Test - zweimal awk aufrufe: $ 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 Würdest du eine raffinierte Möglichkeit kennen, dies in ein awk-Skript wie z. B. ein Muster aufzunehmen? awk '/ mypattern / {do stuff ...}'
Bernie Reiter
@BernieReiter kann man sagen awk 'NF {do stuff...}'.
Fedorqui 'SO hör auf zu schaden'
1
Beachten Sie, dass dadurch auch Zeilen mit Leerzeichen ignoriert werden.
wisbucky
60

sed '/^$/d'sollte in Ordnung sein, erwarten Sie, die Datei an Ort und Stelle zu ändern? Wenn ja, sollten Sie die -iFlagge verwenden.

Vielleicht sind diese Zeilen nicht leer. Wenn dies der Fall ist, schauen Sie sich diese Frage an. Entfernen Sie leere Zeilen aus txtfiles, entfernen Sie Leerzeichen vom Anfang und Ende der Zeile. Ich glaube, das ist es, was Sie erreichen möchten .

Alberto Zaccagni
quelle
Ja. Ich ändere eine Datei. * .csv. Wie soll das -i auf den Befehl sed gesetzt werden?
Jonas
2
sed -i '/^$/d'ist eine Möglichkeit, es zu tun.
Alberto Zaccagni
49

sed

grep

awk

Oleg Mazko
quelle
1
Diese werden in Ihrem Online-Tool korrekt angezeigt, []sollten jedoch nicht in einem Klammerausdruck maskiert werden, sodass der Code hier nicht korrekt ist für \[\[:space:\]\]oder \[ \t\]- sollte [[:space:]]und sein [ \t].
Benjamin W.
1
@ BenjaminW. Danke, dass du das verstanden hast. Diese stammten nicht vom ursprünglichen Autor, sondern stammten aus Edit 3, als es von normalem Text in "Code" geändert wurde, wodurch das "\" Escape "entlarvt" wurde. Ich habe sie jetzt repariert.
wisbucky
30

Ich glaube, das ist das einfachste und schnellste:

cat file.txt | grep .

Wenn Sie auch alle Leerzeichen ignorieren müssen, versuchen Sie Folgendes:

cat file.txt | grep '\S'

Beispiel:

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

Ausgänge

7
5
Vadim
quelle
5
Keine Notwendigkeit cat, grepnimmt auch Dateien:grep . file.txt
Ciro Santilli 法轮功 冠状 病 六四 六四 16
3
Ja, ich weiß, aber in der ersten Frage wurde nicht erwähnt, ob die Quelle eine Datei oder etwas anderes ist. Die Lösung lautet also "|" und davor nur ein Beispiel für eine Quelle. Einfach, um die Lösung von der Quelle der Linien zu unterscheiden.
Vadim
2
grep '\S'ist definitiv nicht tragbar. Wenn Sie haben grep -P, können Sie verwenden, grep -P '\S'aber es wird auch nicht auf allen Plattformen unterstützt.
Tripleee
Der Nachteil im grep .Vergleich zu den anderen Lösungen ist, dass der gesamte Text rot hervorgehoben wird. Die anderen Lösungen können die ursprünglichen Farben beibehalten. Vergleichen Sie unbuffer apt search foo | grep .mitunbuffer apt search foo | grep -v ^$
wisbucky
15

Mit Hilfe der akzeptierten Antwort hier und die akzeptierten Antwort oben, habe ich verwendet:

$ 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

Dies deckt alle Grundlagen ab und funktioniert perfekt für meine Bedürfnisse. Ein großes Lob an die Originalposter @Kent und @kev

Bauernfänger
quelle
5

Sie können sagen:

sed -n '/ / p' filename    #there is a space between '//'
Panzer
quelle
.. was bedeutet print all lines except the empty one(s)und ruhig sein
Timo
2

Sie können so etwas auch mit "grep" machen:

egrep -v "^$" file.txt
Lowbit
quelle
2

Dies funktioniert auch in awk.

awk '!/^$/' file
xxxxxx
yyyyyy
zzzzzz
Claes Wikner
quelle
2

Sie sehen höchstwahrscheinlich das unerwartete Verhalten, weil Ihre Textdatei unter Windows erstellt wurde, sodass die Zeilenende-Sequenz lautet \r\n. Sie können dos2unix verwenden, um es in eine Textdatei im UNIX-Stil zu konvertieren, bevor Sie sed ausführen oder verwenden

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

um Leerzeilen zu entfernen, unabhängig davon, ob der Wagenrücklauf vorhanden ist oder nicht.

FauChristian
quelle
Hallo, was macht die -rFlagge und ist es möglich, sie zu kombinieren -i, um die Datei direkt zu ändern und das Drucken auf dem Bildschirm zu vermeiden. Darüber hinaus denke ich, dass dieser Befehl auch funktionieren würde alssed -r "/^\r$/d"
Alexander Cska
2

Eine weitere Option , ohne sed, awk, perl, usw.

strings $file > $output

Zeichenfolgen - Drucken Sie die Zeichenfolgen druckbarer Zeichen in Dateien.

user319660
quelle
Meinst du stringsstatt string?
Mickael B.
Hallo @MickaelB. Du hast recht, ich repariere es.
user319660
0

Meine bashspezifische Antwort lautet, die Verwendung des perlSubstitutionsoperators mit dem globalen Musterflag gwie folgt zu empfehlen :

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

Diese Antwort veranschaulicht die Berücksichtigung, ob die leeren Zeilen Leerzeichen enthalten ( [\ ]*), und die Verwendung |zum Trennen mehrerer Suchbegriffe / Felder. Getestet auf macOS High Sierra und CentOS 6/7.

Zu Ihrer Information, der ursprüngliche Code des OP sed '/^$/d' $filefunktioniert in bashTerminal unter macOS High Sierra und CentOS 6/7 Linux in einem Hochleistungs-Supercomputing-Cluster einwandfrei.

justincbagley
quelle
-3

Für mich mit FreeBSD 10.1 mit sed funktionierte nur diese Lösung:

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

Im Inneren []befinden sich Leerzeichen und Tabulatorsymbole.

Testdatei enthält:

fffffff next 1 tabline ffffffffffff

ffffffff next 1 Space line ffffffffffff

ffffffff empty 1 lines ffffffffffff

============ EOF =============
Vitaly
quelle