2009-05-28 16 views
27

Ich habe eine Datei, die enthält:Wie kann ich mehrere leere Zeilen durch eine einzelne leere Zeile in bash ersetzen?

something 



something else 

something else again 

ich ein Bash-Befehl benötigen, sed/grep wir, dass die folgende Ausgabe

something 

something else 

something else again 

Mit anderen Worten erzeugen wird, muss ich mehrere Leerzeilen ersetzen mit nur einer einzigen Leerzeile. grep/sed sind linienbasiert. Ich habe noch nie eine BASH-Lösung gefunden, die bei mehrzeiligen Regex-Mustern funktioniert.

+0

Schnell Klärung Frage: Hat die Datei Zeilen, die * nicht * durch eine Leerzeile getrennt sind? – biggusjimmus

+3

Haben Sie jemals doppelte Zeilen, die nicht leer sind? Wenn nicht, könnten Sie uniq verwenden. –

+0

Es gibt Linien, die nicht durch eine Leerzeile getrennt sind. Es könnte doppelte Zeilen geben. –

Antwort

65

Für BSD-basierten Systemen (einschließlich GNU):

Sie haben soeben cat mit der -s Option benötigen, die bewirkt, dass es leer wiederholt entfernen Linien von seinem Ausgang:

cat -s 

von Manpage: -s --squeeze-blank: suppress repeated empty output lines.

+0

Duh. Perfekte Lösung. –

+3

aus irgendeinem Grund funktioniert das nicht für mich 'cat -s file1> file2' – qodeninja

+4

@qodeninja Es funktionierte nicht für mich, auch wenn ich mit Dateien mit Windows-Zeilenenden arbeitete. Vielleicht könnte das auch für dich das Problem sein? Als ich die Dateien in Unix Zeilenendungen umwandelte, funktionierte 'cat -s' für mich. –

1

Verwenden Python:

s = file("filename.txt").read() 
while "\n\n\n" in s: s = s.replace("\n\n\n", "\n\n") 
import sys 
sys.stdout.write(s) 
+0

das ist ineffizient while-Schleife – user5672998

-1

Super einfach mit vim zu tun. Öffnen Sie einfach die Datei und geben Sie Folgendes ein:

:%s/\n\n\n*/\r\r/ 

Das wird alle Blöcke von mehr als 2 neuen Zeilen auf 2 neue Zeilen reduzieren. Hoffe das hilft!

6

Eigentlich, wenn Sie mehrere Zeilen mit einem einzigen Newline ersetzen, würde der Ausgang sein:

something 
something else 
something else again 

Sie dies erreichen können:

sed /^$/d FILE 
+0

Das ist offensichtlich, offensichtlich :) Was OP bedeutet wahrscheinlich ist, ersetzen mehrere "leer" (beachten Sie, dass dies nicht unbedingt leer ist, da Zeilen können unsichtbaren Leerraum) mit einer leeren Zeile (wenn es nicht ist am Anfang oder Ende der Sequenz) bedeutet zwei Newline-Zeichen. – arielf

-2

Ich nehme an, dass Sie wahrscheinlich werden wollen um Zeilen zu entfernen, die nur Leerzeichen enthalten.

, die mit getan werden kann:

sed /^[:space:]*$/d FILE 
2

Eine Lösung mit awk, die mehrere Leerzeilen mit einer einzigen Leerzeile ersetzt:

awk 'BEGIN{bl=0}/^$/{bl++;if(bl==1)print;else next}/^..*$/{bl=0;print}' myfile 
+0

+1: Große Köpfe denken gleich: P –

2

Normalerweise, wenn ich, dass sed finden kann nicht tun etwas, was ich brauche, wende ich mich an awk:

awk ' 
BEGIN { 
    blank = 0; 
} 

/^[[:blank:]]*$/ { 
    if (!blank) { 
      print; 
    } 
    blank = 1; 
    next; 
} 

{ 
    print; 
    blank = 0; 
}' file 
+0

Ihre Lösung ist besser lesbar! – mouviciel

12
grep -A1 . <yourfile> | grep -v "^--$" 

Diese grep Lösung funktioniert, wie Sie wollen, dass die Annahme folgenden:

Eingang

line1 

line2 
line3 


line4 



line5

Ausgabe

line1 

line2 
line3 

line4 

line5
+0

Perfekt. Vielen Dank! –

+0

Ich mag es, sehr elegante Lösung – duckyflip

+3

Frickin 'brilliant, eigentlich. Ich hätte das in einer Million Jahren nicht gemacht. Gute Arbeit. Eine leicht robustere Version geht natürlich so (um nicht leere Leerzeilen zu handhaben): grep -v -A1 '^ [[: blank:]] * $' | grep -v '^ - $' –

-4

es Pipelining | uniq kann Lösung sein (falls andere als leere Zeilen nicht duplizieren)

1

Wenn jemand verwenden perl wollen

perl -00pe0 < file 

wird das gleiche tun, wie cat -s :)

2

Diese marco's solution auf mehrere Dateien verwendet:

for i in *; do FILE=$(cat -s "$i"); echo "$FILE" > "$i"; done 
9

ich dieses Problem durch sed nur gelöst. Auch wenn dies eine 7 Jahre alte Frage, hier kann jemand kann um Hilfe, so schreibe ich meine Lösung von sed hier:

sed 'N;/^\n$/D;P;D;' 
+1

Das funktioniert gut für mich, und weil es sed ist, kann ich -i für In-Place-Fixes verwenden. – Kieran

+0

Ansonsten löscht das auch die letzten 2 Zeilen für die Datei (auf OSX sed) – Nivco

0

Python, mit regulären Ausdrücken:

import re 
import sys 
sys.stdout.write(re.sub('\n{2,}','\n\n', sys.stdin.read())) 
Verwandte Themen