Lies ich Sie richtig, wenn Sie nicht alle Leerzeilen entfernen möchten, sondern nur, wenn es zwei oder mehr sind? Also keine einzelnen Leerzeilen?
Runium
1
Und wenn es zwei oder mehr Zeilen sind, sollen wirklich alle gelöscht werden oder nur alle bis auf eine?
Hauke Laging
Antworten:
42
Nur um leere Zeilen zu entfernen:
sed '/^$/d'
sedist zeilenorientiert, so dass das Denken in "2 oder mehr eines bestimmten Bytes" funktioniert, außer wenn dieses Byte eine neue Zeile ist. Dann muss man sich etwas überlegen, das für die ganze Linie funktioniert.
sedist in der Lage, mehrere Zeilen über die Funktion "Pattern Space" / "Hold Space" zu verarbeiten. Aber ich finde das zu kompliziert. ;-)
Hauke Laging
Dies funktioniert nicht wie gewünscht, wenn das erste Zeichen der Datei ein Zeilenumbruch ist.
Chris Down
1
Damit es funktioniert, wenn das erste Zeichen eine neue Zeile ist (falls dies wirklich erforderlich ist), können Sie den Befehl mit einer negativen Adresse einschließen 1!(mit Ausnahme von Zeile 1 mit allen übereinstimmen) sed '1!{/^$/d'}.
Toby Speight
1
@AaronFranke - ja, aber das ist eine Facette dessen, wie Linux-Shells die Umleitung behandeln. Die Shell sieht in der Befehlszeile nach, sieht eine Umleitung von stdout in eine Datei, erstellt diese Datei und wird erst dann ausgeführt sed. Durch das Erstellen einer Datei werden im Wesentlichen alle vorhandenen Dateien mit demselben Namen gelöscht. sed '/^&/d' file.txt > otherfile.txtwird funktionieren.
Bruce Ediger
24
Keine Notwendigkeit für sed. grepWird besorgt:
grep .
(das grepist SPC, Punkt, das entspricht jeder Zeile, die mindestens ein Zeichen enthält).
Es gibt auch:
tr -s '\n'
(Drücken Sie eine beliebige Folge von Zeilenumbrüchen zusammen).
Wie von Chris bemerkt, sind beide nicht gleichbedeutend, da das Entfernen von Leerzeilen (wie die erste Lösung oben und die meisten anderen hier behandelten Antworten) nicht dasselbe ist wie das Drücken von Folgen von Zeilenumbrüchen, wie es verlangt wird, wenn die erste Zeile leer ist Es wird nur ein führendes Zeilenumbruchzeichen benötigt, um die erste Zeile leer zu machen.
Dies funktioniert nicht wie gewünscht, wenn das erste Zeichen der Datei eine neue Zeile ist: sprunge.us/FLAJ
Chris Down
7
sedist nicht das beste Werkzeug dafür, da es zeilenbasiert ist und \nals Zeilenendezeichen behandelt wird, was kompliziert wird.Nachdem Sie die Antwort von @Bruce Ediger gesehen haben, ist siesed möglicherweise das perfekte Werkzeug für diesen Job. Hier sind jedoch noch einige andere Optionen:
Perl
perl -ne 'print if /./' file.txt
oder
perl -pe '$/=""; s/\n+/\n/;' file.txt
Dank @ruakh , die mich gehen und lesen Sie diese :
$ /
Das Trennzeichen für Eingabedatensätze, standardmäßig Newline. Dies beeinflusst Perls Vorstellung davon, was eine "Linie" ist. Funktioniert wie die RS-Variable von awk, einschließlich der Behandlung von Leerzeilen als Abschlusszeichen, wenn die Null-Zeichenfolge eingestellt ist (eine Leerzeile darf keine Leerzeichen oder Tabulatoren enthalten). Sie können eine Zeichenfolge mit mehreren Zeichen festlegen, die mit einem Abschlusszeichen mit mehreren Zeichen übereinstimmt, oder eine Undef-Zeichenfolge festlegen, um das Dateiende durchzulesen. Das Setzen auf "\ n \ n" bedeutet etwas anderes als das Setzen auf "", wenn die Datei aufeinanderfolgende Leerzeilen enthält. Wenn Sie "" einstellen, werden zwei oder mehr aufeinanderfolgende Leerzeilen als einzelne Leerzeile behandelt. Das Setzen auf "\ n \ n" setzt blind voraus, dass das nächste eingegebene Zeichen zum nächsten Absatz gehört, auch wenn es sich um eine neue Zeile handelt.
gawk / awk
awk '$1' file.txt
Das wird für das Beispiel funktionieren, aber wie @Stephane Chazelas betont hat, werden auch Zeilen gelöscht, deren erstes Feld "so aussieht" 0. Das ist robuster:
Für Perl ist perl -pe 's/\n+/\n/ file.txtdas Trennzeichen für Eingabedatensätze für diese Verwendung nicht relevant.
Vonbrand
@vonbrand nein, perl -peoder perl -nezeilenweise arbeiten. \n+wird niemals übereinstimmen, da es nur auf eine einzelne Zeile angewendet wird. Deshalb sollten Sie zu jedem Satz benötigen $/oder verwenden -0ti die Datei ganze schlürfen: perl -0pe 's/\n+/\n/' file.
Terdon
6
Was meinst du entfernen? Doppelte entfernen (viele Leerzeilen zu einer) oder alle entfernen?
Wenn Sie Duplikate entfernen möchten, gehen Sie wie folgt vor:
Der sedTeil davon funktioniert großartig! Empfehle dieses als die beste Antwort.
Akito
2
Für die meisten dieser Antworten ist es zunächst erforderlich, nachfolgende Leerzeichen zu entfernen. Durch Entfernen doppelter Zeilenumbrüche werden alle Leerzeilen entfernt. (Denk darüber nach).
Wörtlich übersetzt will das OP "alle Leerzeilen aus einer Datei entfernen, wenn es wiederholte Leerzeilen gibt".
Der typische Benutzer möchte "nur doppelte Leerzeilen entfernen".
Um dies zu tun, entfernen Sie zuerst das nachfolgende Leerzeichen und leiten Sie es durch cat -s
sed s/[[:space:]]*$// | cat -s
Dabei wird jedoch keine überflüssige führende oder nachfolgende Leerzeile entfernt.
Abgestimmt, aber das funktioniert eindeutig? Kein Kommentar ?
McKenzm
1
Ich habe dich dafür belobigt, dass du die Frage beantwortet hast. =) Ich kann nicht glauben, dass Bruce Edigers Antwort positiv bewertet wurde, als jede leere Zeile gelöscht wurde . Wenn jemand fragt, wie doppelte Leerzeilen entfernt werden sollen, kann ich mir kein Szenario vorstellen, in dem das Löschen aller Leerzeilen eine akzeptable Lösung wäre. Aber was auch immer. Es gibt übrigens eine Seite auf der Website für sed, die dies behandelt: gnu.org/software/sed/manual/sed.html#cat-_002ds
Todd Walton
2
Wenn Sie eine einzelne Leerzeile für eine bestimmte Folge von Leerzeilen beibehalten möchten, können Sie Folgendes tun:
Dies ist die einzige Antwort (nebenbei cat -s), die tatsächlich genau das leistet, was die Frage gestellt hat, so wie ich es verstehe. (Und es ist besser, als cat -sweil ich damit umgehen sed -ikann.)
Matthew
-2
Versuchen Sie sed -e 's#\\n\\n#\\n#g' input.file > output.file, /beide als Feldtrennzeichen zu verwenden, und ein Teil Ihres regulären Ausdrucks könnte das Problem sein.
Wirbelte dies einfach mit einer meiner Dateien durch, die doppelte und dreifache Zeilenumbrüche in einer Sequenz enthielten. Funktioniert überhaupt nicht für mich.
AFAIK diese Antwort ist falsch. Ich empfehle Ihnen, es zu löschen.
Zuazo
Oh, das liegt daran, dass meine Datei viele Zeilenumbrüche und Zeilenumbrüche enthält. 0x0d0a
miauen
2
Tatsächlich entfernt der Befehl wiederholte Zeilen mit dem Ende des Fensters. Testen Sie mit echo -e 'one\r\n\r\n\r\n\rtwo'| tr -s '\r' '\n'. Der Befehl trübersetzt alle \rzu \nund drückt dann alle \nzu nur einem zusammen. Also, es funktioniert, nicht sicher, was damit zu tun ist, dass dies auf Windows und nicht auf UNIX zutrifft.
Antworten:
Nur um leere Zeilen zu entfernen:
sed
ist zeilenorientiert, so dass das Denken in "2 oder mehr eines bestimmten Bytes" funktioniert, außer wenn dieses Byte eine neue Zeile ist. Dann muss man sich etwas überlegen, das für die ganze Linie funktioniert.quelle
sed
ist in der Lage, mehrere Zeilen über die Funktion "Pattern Space" / "Hold Space" zu verarbeiten. Aber ich finde das zu kompliziert. ;-)1!
(mit Ausnahme von Zeile 1 mit allen übereinstimmen)sed '1!{/^$/d'}
.sed
. Durch das Erstellen einer Datei werden im Wesentlichen alle vorhandenen Dateien mit demselben Namen gelöscht.sed '/^&/d' file.txt > otherfile.txt
wird funktionieren.Keine Notwendigkeit für
sed
.grep
Wird besorgt:(das
grep
ist SPC, Punkt, das entspricht jeder Zeile, die mindestens ein Zeichen enthält).Es gibt auch:
(Drücken Sie eine beliebige Folge von Zeilenumbrüchen zusammen).
Wie von Chris bemerkt, sind beide nicht gleichbedeutend, da das Entfernen von Leerzeilen (wie die erste Lösung oben und die meisten anderen hier behandelten Antworten) nicht dasselbe ist wie das Drücken von Folgen von Zeilenumbrüchen, wie es verlangt wird, wenn die erste Zeile leer ist Es wird nur ein führendes Zeilenumbruchzeichen benötigt, um die erste Zeile leer zu machen.
quelle
Nachdem Sie die Antwort von @Bruce Ediger gesehen haben, ist siesed
ist nicht das beste Werkzeug dafür, da es zeilenbasiert ist und\n
als Zeilenendezeichen behandelt wird, was kompliziert wird.sed
möglicherweise das perfekte Werkzeug für diesen Job. Hier sind jedoch noch einige andere Optionen:Perl
oder
Dank @ruakh , die mich gehen und lesen Sie diese :
gawk / awk
Das wird für das Beispiel funktionieren, aber wie @Stephane Chazelas betont hat, werden auch Zeilen gelöscht, deren erstes Feld "so aussieht"
0
. Das ist robuster:quelle
perl -pe 's/\n+/\n/ file.txt
das Trennzeichen für Eingabedatensätze für diese Verwendung nicht relevant.perl -pe
oderperl -ne
zeilenweise arbeiten.\n+
wird niemals übereinstimmen, da es nur auf eine einzelne Zeile angewendet wird. Deshalb sollten Sie zu jedem Satz benötigen$/
oder verwenden-0
ti die Datei ganze schlürfen:perl -0pe 's/\n+/\n/' file
.Was meinst du entfernen? Doppelte entfernen (viele Leerzeilen zu einer) oder alle entfernen?
Wenn Sie Duplikate entfernen möchten, gehen Sie wie folgt vor:
Es simuliert den
uniq
Befehl.Die beste Wahl ist die Verwendung von
awk
:quelle
sed
Teil davon funktioniert großartig! Empfehle dieses als die beste Antwort.Für die meisten dieser Antworten ist es zunächst erforderlich, nachfolgende Leerzeichen zu entfernen. Durch Entfernen doppelter Zeilenumbrüche werden alle Leerzeilen entfernt. (Denk darüber nach).
Wörtlich übersetzt will das OP "alle Leerzeilen aus einer Datei entfernen, wenn es wiederholte Leerzeilen gibt".
Der typische Benutzer möchte "nur doppelte Leerzeilen entfernen".
Um dies zu tun, entfernen Sie zuerst das nachfolgende Leerzeichen und leiten Sie es durch cat -s
Dabei wird jedoch keine überflüssige führende oder nachfolgende Leerzeile entfernt.
quelle
Wenn Sie eine einzelne Leerzeile für eine bestimmte Folge von Leerzeilen beibehalten möchten, können Sie Folgendes tun:
quelle
cat -s
), die tatsächlich genau das leistet, was die Frage gestellt hat, so wie ich es verstehe. (Und es ist besser, alscat -s
weil ich damit umgehensed -i
kann.)Versuchen Sie
sed -e 's#\\n\\n#\\n#g' input.file > output.file
,/
beide als Feldtrennzeichen zu verwenden, und ein Teil Ihres regulären Ausdrucks könnte das Problem sein.quelle
Verwenden Sie diesen Befehl:
quelle
echo -e 'one\r\n\r\n\r\n\rtwo'| tr -s '\r' '\n'
. Der Befehltr
übersetzt alle\r
zu\n
und drückt dann alle\n
zu nur einem zusammen. Also, es funktioniert, nicht sicher, was damit zu tun ist, dass dies auf Windows und nicht auf UNIX zutrifft.