2009-05-28 9 views
27

Mam plik, który zawiera:Jak mogę zamienić wiele pustych linii na pojedynczą pustą linię w bash?

something 



something else 

something else again 

muszę polecenia bash, sed/grep nam, że będzie następujący wynik

something 

something else 

something else again 

Innymi słowy, muszę wymienić kilka pustych linii z pojedynczą pustą linią. grep/sed są oparte na liniach. Nigdy nie znalazłem rozwiązania BASH, które działałoby na wielowierszowych wzorach regex.

+0

Szybkie wyjaśnienie pytanie: Czy plik ma zawsze wiersze, które * nie są * rozdzielone pustą linią? – biggusjimmus

+3

Czy masz zduplikowane wiersze, które nie są puste? Jeśli nie, możesz użyć uniq. –

+0

Istnieją linie, które nie są oddzielone pustym wierszem. Mogą występować zduplikowane linie. –

Odpowiedz

65

Dla systemów BSD-pochodzi (w tym GNU):

wystarczy cat z opcją -s co powoduje go do usunięcia powtarzane pusty linie z jego wyjścia:

cat -s 

ze strony człowieka: -s --squeeze-blank: suppress repeated empty output lines.

+0

Duh. Idealne rozwiązanie. –

+3

z jakiegokolwiek powodu, który nie działa dla mnie 'cat -s file1> file2' – qodeninja

+4

@qodeninja Nie działało to dla mnie, gdy pracowałem z plikami z zakończeniami linii Windows. Może to też może być problem dla ciebie? Kiedy konwertowałem pliki na końcówki linii Unix, "cat -s" działało dobrze dla mnie. –

1

Zastosowanie 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

to jest niewydajne, podczas gdy pętla – user5672998

-1

Super łatwe do zrobienia z vim. Po prostu otwórz plik i wpisz:

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

To zredukuje wszystkie bloki o więcej niż 2 nowe linie do 2 nowych linii. Mam nadzieję że to pomoże!

6

Właściwie, jeśli zastąpienie wielu nowych linii z jednym znakiem nowej linii, wyjście będzie:

something 
something else 
something else again 

Można to osiągnąć przez:

sed /^$/d FILE 
+0

Jest to poprawne, oczywiście :) Jakie OP prawdopodobnie oznaczało zastąpienie wielu "pustych" (zwróć uwagę, że to niekoniecznie jest puste, ponieważ linie mogą mieć niewidzialną białą przestrzeń) z jedną pustą linią (która, chyba że to znajduje się na początku lub na końcu sekwencji) oznacza dwa znaki nowej linii. – arielf

-2

Rozumiem, że prawdopodobnie będziesz chciał aby usunąć linie, które mają tylko spacje.

To może być wykonane z:

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

Rozwiązanie z awk, które zastępuje kilka wierszy z jednym pustym wierszem:

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

+1: Wielkie umysły myślą podobnie: P –

2

Zazwyczaj, jeśli okaże się, że nie mogę sed zrób coś, czego potrzebuję, zwracam się do awk:

awk ' 
BEGIN { 
    blank = 0; 
} 

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

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

Twoje rozwiązanie jest bardziej czytelne! – mouviciel

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

To rozwiązanie działa grep zakładając chcesz, co następuje:

Wejście

line1 

line2 
line3 


line4 



line5

Wyjście

line1 

line2 
line3 

line4 

line5
+0

Idealny. Dziękujemy! –

+0

Podoba mi się, bardzo eleganckie rozwiązanie – duckyflip

+3

Frickin 'genialny, faktycznie. Nie wymyśliłbym tego od miliona lat. Dobra robota. Wersja nowsza i bardziej rozbudowana wygląda tak (oczywiście w przypadku niepustych pustych linii): grep -v -A1 '^ [[: blank:]] * $' | grep -v '^ - $' –

-4

Montaż rurociągów go | uniq może być rozwiązaniem (jeśli inny niż pustych linii nie powielać)

1

Jeśli ktoś chce użyć Perl

perl -00pe0 < file 

zrobi to samo, jak cat -s :)

2

używa marco's solution na wielu plikach:

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

po prostu rozwiązać ten problem przez sed. Nawet jeśli jest to 7 lat pytanie, może ktoś może tutaj o pomoc, więc piszę moje rozwiązania przez sed tutaj:

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

To działa dobrze dla mnie, a ponieważ jest to sed, mogę użyć -i dla poprawek w miejscu. – Kieran

+0

Wiernie to usuwa również 2 ostatnie wiersze pliku dla mnie (na OSx sed) – Nivco

0

Python, z wyrażenia regularnego:

import re 
import sys 
sys.stdout.write(re.sub('\n{2,}','\n\n', sys.stdin.read())) 
Powiązane problemy