Czy czytam cię poprawnie, jeśli nie chcesz usunąć wszystkich pustych wierszy, ale tylko jeśli są to dwa lub więcej. Więc nie ma pojedynczych pustych linii?
Runium
1
A jeśli to dwie lub więcej linii, czy naprawdę należy je wszystkie usunąć, czy tylko wszystkie oprócz jednej?
Hauke Laging
Odpowiedzi:
42
Aby usunąć puste linie:
sed '/^$/d'
sedjest zorientowany na linię, więc myślenie w kategoriach „2 lub więcej określonego bajtu” działa, z wyjątkiem sytuacji, gdy ten bajt jest znakiem nowej linii. Następnie musisz wymyślić coś, co zadziała dla całej linii.
sedjest w stanie obsłużyć kilka linii za pomocą funkcji „przestrzeni wzorów” / „przestrzeni trzymania” Ale czuję, że to zbyt skomplikowane. ;-)
Hauke Laging
Nie będzie działać zgodnie z oczekiwaniami, jeśli pierwszym znakiem pliku jest nowa linia.
Chris Down,
1
Aby to działało, gdy pierwszy znak jest znak nowej linii (jeśli jest to naprawdę to wymóg), to można ująć polecenia z adresem ujemnej 1!(mecz wszystko z wyjątkiem linii nr 1), w następujący sposób: sed '1!{/^$/d'}.
Toby Speight
1
@AaronFranke - tak, ale jest to aspekt tego, jak powłoki Linux traktują przekierowanie „>”. Powłoka patrzy na wiersz poleceń, widzi przekierowanie standardowego wejścia do pliku, tworzy ten plik i dopiero wtedy uruchamia się sed. Utworzenie pliku spowoduje usunięcie dowolnego istniejącego pliku o tej samej nazwie. sed '/^&/d' file.txt > otherfile.txtbędzie działać.
Bruce Ediger,
24
Nie ma potrzeby sed. grepzrobi:
grep .
(to grepznaczy SPC, kropka, czyli pasuje do dowolnej linii zawierającej co najmniej jeden znak).
Jest także:
tr -s '\n'
(ściśnij dowolną sekwencję znaków nowej linii w jedną).
Jak zauważył Chris, oba nie są równoważne, ponieważ usuwanie pustych linii (jak pierwsze rozwiązanie powyżej i większość innych odpowiedzi skupia się tutaj) nie jest tym samym, co ściskanie sekwencji znaków nowego wiersza zgodnie z żądaniem w przypadku, gdy pierwszy wiersz jest pusty, ponieważ zajmuje tylko jeden wiodący znak nowej linii, aby pierwszy wiersz był pusty.
Nie będzie działać zgodnie z oczekiwaniami, jeśli pierwszym znakiem pliku jest nowa linia: sprunge.us/FLAJ
Chris Down
7
sednie jest najlepszym narzędziem do tego, ponieważ jest oparty na linii i traktuje \njako znak końca linii, co komplikuje się.Widząc @Bruce EDIGER za odpowiedźsed może okazać się doskonałym narzędziem do pracy, nadal, oto niektóre inne opcje:
Perl
perl -ne 'print if /./' file.txt
lub
perl -pe '$/=""; s/\n+/\n/;' file.txt
Dzięki @ruakh, który zmusił mnie do przeczytania tego :
$ /
Separator rekordów wejściowych, domyślnie nowy wiersz. Wpływa to na wyobrażenie Perla o tym, czym jest „linia”. Działa jak zmienna RS awk, włączając traktowanie pustych linii jako terminatora, jeśli jest ustawiony na ciąg pusty (pusty wiersz nie może zawierać spacji ani tabulatorów). Możesz ustawić ciąg znaków składający się z wielu znaków, aby dopasować terminator zawierający wiele znaków lub cofnąć, aby odczytać koniec pliku. Ustawienie go na „\ n \ n” oznacza coś nieco innego niż ustawienie na „”, jeśli plik zawiera kolejne puste wiersze. Ustawienie „” potraktuje dwie lub więcej następujących po sobie pustych linii jako pojedynczą pustą linię. Ustawienie na „\ n \ n” będzie ślepo zakładać, że następny znak wejściowy należy do następnego akapitu, nawet jeśli jest to nowy wiersz.
gawk / awk
awk '$1' file.txt
Będzie to działać w opublikowanym przykładzie, ale jak wskazał @Stephane Chazelas , usunie również wiersze, których pierwsze pole „wygląda” 0. Jest to bardziej niezawodne:
W przypadku Perla perl -pe 's/\n+/\n/ file.txtseparator rekordów wejściowych nie ma znaczenia dla tego zastosowania.
vonbrand
@ vonbrand no perl -pelub perl -nepraca linia po linii. \n+nigdy nie będzie pasować, ponieważ jest stosowany tylko w jednym wierszu. Dlatego trzeba albo ustawić $/lub użyj -0ti slurp plik całości: perl -0pe 's/\n+/\n/' file.
terdon
6
Co masz na myśli usunąć? usunąć duplikat (wiele pustych wierszy do jednego) czy usunąć wszystkie?
Jeśli chcesz usunąć duplikat, oto metoda wykorzystująca sed:
Ta sedczęść działa świetnie! Polecając ten jako najlepszą odpowiedź.
Akito
2
W przypadku większości tych odpowiedzi należy najpierw usunąć końcowe białe znaki. Usunięcie podwójnych linii nowych usuwa wszystkie puste linie. (Pomyśl o tym).
Dosłownie zinterpretowana OP chce „usunąć wszystkie puste linie z pliku, jeśli występują powtarzające się puste linie”.
Typowy użytkownik chce „usunąć tylko zduplikowane puste linie”.
Aby to zrobić, najpierw usuń końcowe białe spacje i potokuj przez cat -s
sed s/[[:space:]]*$// | cat -s
A jednak nie usunie to zbędnej początkowej lub końcowej pustej linii.
Przesłuchany, ale to wyraźnie działa? Bez komentarza ?
mckenzm,
1
Głosowałem za ... no wiesz ... odpowiadając na pytanie. =) Nie mogę uwierzyć, że odpowiedź Bruce'a Edigera została pozytywnie oceniona, gdy usuwa każdą pustą linię. Jeśli ktoś zapyta, jak usunąć zduplikowane puste linie, nie wyobrażam sobie żadnego scenariusza, w którym usunięcie wszystkich pustych linii byłoby akceptowalnym rozwiązaniem. Ale cokolwiek. Nawiasem mówiąc
Todd Walton
2
Jeśli chcesz zachować jedną pustą linię dla dowolnej sekwencji pustych linii, możesz:
Jest to jedyna odpowiedź (poza tym cat -s), która faktycznie spełnia dokładnie to pytanie, jakie rozumiem. (I to jest lepsze niż cat -sdlatego, że mogę sed -iz tym korzystać.)
Matthew
-2
Spróbuj sed -e 's#\\n\\n#\\n#g' input.file > output.fileużyć /obu jako separatora pól, a część wyrażenia regularnego może być problemem.
AFAIK ta odpowiedź jest niepoprawna. Polecam usunąć go.
zuazo
och, to dlatego, że mój plik zawiera wiele znaków nowego wiersza i zwrotów karetki. 0x0d0a
meow
2
W rzeczywistości polecenie usuwa powtarzające się linie z końcem linii systemu Windows. Przetestuj za pomocą echo -e 'one\r\n\r\n\r\n\rtwo'| tr -s '\r' '\n'. Polecenie trprzetłumaczy wszystko \rna, \na następnie ścisnie wszystko \ndo jednego. Więc działa, nie wiem, co zrobić z faktem, że dotyczy to systemu Windows, a nie UNIX.
Odpowiedzi:
Aby usunąć puste linie:
sed
jest zorientowany na linię, więc myślenie w kategoriach „2 lub więcej określonego bajtu” działa, z wyjątkiem sytuacji, gdy ten bajt jest znakiem nowej linii. Następnie musisz wymyślić coś, co zadziała dla całej linii.źródło
sed
jest w stanie obsłużyć kilka linii za pomocą funkcji „przestrzeni wzorów” / „przestrzeni trzymania” Ale czuję, że to zbyt skomplikowane. ;-)1!
(mecz wszystko z wyjątkiem linii nr 1), w następujący sposób:sed '1!{/^$/d'}
.sed
. Utworzenie pliku spowoduje usunięcie dowolnego istniejącego pliku o tej samej nazwie.sed '/^&/d' file.txt > otherfile.txt
będzie działać.Nie ma potrzeby
sed
.grep
zrobi:(to
grep
znaczy SPC, kropka, czyli pasuje do dowolnej linii zawierającej co najmniej jeden znak).Jest także:
(ściśnij dowolną sekwencję znaków nowej linii w jedną).
Jak zauważył Chris, oba nie są równoważne, ponieważ usuwanie pustych linii (jak pierwsze rozwiązanie powyżej i większość innych odpowiedzi skupia się tutaj) nie jest tym samym, co ściskanie sekwencji znaków nowego wiersza zgodnie z żądaniem w przypadku, gdy pierwszy wiersz jest pusty, ponieważ zajmuje tylko jeden wiodący znak nowej linii, aby pierwszy wiersz był pusty.
źródło
Widząc @Bruce EDIGER za odpowiedźsed
nie jest najlepszym narzędziem do tego, ponieważ jest oparty na linii i traktuje\n
jako znak końca linii, co komplikuje się.sed
może okazać się doskonałym narzędziem do pracy, nadal, oto niektóre inne opcje:Perl
lub
Dzięki @ruakh, który zmusił mnie do przeczytania tego :
gawk / awk
Będzie to działać w opublikowanym przykładzie, ale jak wskazał @Stephane Chazelas , usunie również wiersze, których pierwsze pole „wygląda”
0
. Jest to bardziej niezawodne:źródło
perl -pe 's/\n+/\n/ file.txt
separator rekordów wejściowych nie ma znaczenia dla tego zastosowania.perl -pe
lubperl -ne
praca linia po linii.\n+
nigdy nie będzie pasować, ponieważ jest stosowany tylko w jednym wierszu. Dlatego trzeba albo ustawić$/
lub użyj-0
ti slurp plik całości:perl -0pe 's/\n+/\n/' file
.Co masz na myśli usunąć? usunąć duplikat (wiele pustych wierszy do jednego) czy usunąć wszystkie?
Jeśli chcesz usunąć duplikat, oto metoda wykorzystująca sed:
Symuluje
uniq
polecenie.Najlepszym wyborem jest użycie
awk
:źródło
sed
część działa świetnie! Polecając ten jako najlepszą odpowiedź.W przypadku większości tych odpowiedzi należy najpierw usunąć końcowe białe znaki. Usunięcie podwójnych linii nowych usuwa wszystkie puste linie. (Pomyśl o tym).
Dosłownie zinterpretowana OP chce „usunąć wszystkie puste linie z pliku, jeśli występują powtarzające się puste linie”.
Typowy użytkownik chce „usunąć tylko zduplikowane puste linie”.
Aby to zrobić, najpierw usuń końcowe białe spacje i potokuj przez cat -s
A jednak nie usunie to zbędnej początkowej lub końcowej pustej linii.
źródło
Jeśli chcesz zachować jedną pustą linię dla dowolnej sekwencji pustych linii, możesz:
źródło
cat -s
), która faktycznie spełnia dokładnie to pytanie, jakie rozumiem. (I to jest lepsze niżcat -s
dlatego, że mogęsed -i
z tym korzystać.)Spróbuj
sed -e 's#\\n\\n#\\n#g' input.file > output.file
użyć/
obu jako separatora pól, a część wyrażenia regularnego może być problemem.źródło
Użyj tego polecenia:
źródło
echo -e 'one\r\n\r\n\r\n\rtwo'| tr -s '\r' '\n'
. Polecenietr
przetłumaczy wszystko\r
na,\n
a następnie ścisnie wszystko\n
do jednego. Więc działa, nie wiem, co zrobić z faktem, że dotyczy to systemu Windows, a nie UNIX.