Usuń puste linie za pomocą grep


Odpowiedzi:


300

Spróbuj wykonać następujące czynności:

grep -v -e '^$' foo.txt

Ta -eopcja umożliwia dopasowywanie wzorców wyrażeń regularnych.

Pojedyncze cudzysłowy ^$sprawiają, że działa to w Cshell. Inne powłoki będą zadowolone z cudzysłowów pojedynczych lub podwójnych.

AKTUALIZACJA: Działa to dla mnie dla pliku z pustymi liniami lub „wszystkimi białymi znakami” (takimi jak linie okien z końcówkami linii w stylu „\ r \ n”), podczas gdy powyższe usuwa tylko pliki z pustymi liniami i końcówkami linii w stylu unixowym:

grep -v -e '^[[:space:]]*$' foo.txt

Ten egrep działałby tylko dla plików z zerową lub 1 spacją w wierszu, a nie dla plików z 2 lub więcej spacjami. Zmiana ? do *.
Ed Morton,

4
Tak powinno być grep -E -v, wszystko później -ejest interpretowane jako wzorzec.
jazzpi

6
grep -v -e '^[[:space:]]*$' -e '^#' filewyświetli wszystkie niepuste, nie będące komentarzami wiersze w skrypcie lub pliku konfiguracyjnym (lub dowolnym typie pliku, który używa znaku krzyżyka dla komentarzy).
palswim

„Ta -eopcja umożliwia dopasowywanie wzorców regex”. To jest bardzo mylące . -ejest (POSIX-) definicją dla: This can be used to specify multiple search patterns, or to protect a pattern beginning with a hyphen (-).(z podręcznika ). Grep już domyślnie oczekuje (podstawowego) wyrażenia regularnego. Z tego wzoru, można pominąć -ew całości: grep -v '^[[:space:]]*$' foo.txt.
Yeti

73

Nie komplikuj.

grep . filename.txt

1
to daje mi wszystkie linie w pliku
phuclv

2
@ LưuVĩnhPhúc Powinien wypisać wszystkie wiersze w pliku z wyjątkiem pustych wierszy.
Frej Connolly,

2
Działa to dla mnie na plikach z systemu Linux, ale nie na plikach z Windows. Prawdopodobnie z powodu znaków końca linii systemu Windows.

Głosuję za tym, mimo że nie do końca rozwiązuje to problem OP z obsługą pliku z zakończeniami linii Windows, ale ponieważ nie mam tego problemu, okazało się to dla mnie idealnym rozwiązaniem.
David Z

1
To idealne rozwiązanie. Prosty i działający w systemie Linux.
W00f

30

Posługiwać się:

$ dos2unix file
$ grep -v "^$" file

Lub po prostu awk:

awk 'NF' file

Jeśli nie masz dos2unix, możesz użyć narzędzi takich jak tr :

tr -d '\r' < "$file" > t ; mv t "$file"

Nie można znaleźć programu dos2unix. Czy to dla systemu Windows? polecenie ask też nie działa.
węzeł ninja

zapytać? Nie, to jest awk.
iconoclast

Dobra uwaga na temat konwersji na zakończenia linii w stylu UNIX, w przeciwnym razie wyrażenia regularne mogą nie działać zgodnie z oczekiwaniami. Nic tutaj nie działało, dopóki nie przekonwertowałem końcówek linii.
Ryan H.

16
grep -v "^[[:space:]]*$"

The -v makes it print lines that do not completely match

===Each part explained===
^             match start of line
[[:space:]]   match whitespace- spaces, tabs, carriage returns, etc.
*             previous match (whitespace) may exist from 0 to infinite times
$             match end of line

Uruchamianie kodu

$ echo "
> hello
>       
> ok" |
> grep -v "^[[:space:]]*$"
hello
ok

Aby dowiedzieć się więcej o tym, jak / dlaczego to działa, polecam przeczytanie o wyrażeniach regularnych. http://www.regular-expressions.info/tutorial.html


2
Jak i dlaczego to działa? Twoja odpowiedź byłaby znacznie lepsza, gdybyś mógł to wyjaśnić. Na przykład, twoje wyrażenie regularne dopasowuje początek łańcucha, a następnie jedną lub więcej spacji przy użyciu standardu POSIX, a następnie koniec łańcucha, tj. Za pomocą grep -v usuwa wszystkie linie, które są tylko spacjami. Dobrze? Co się stanie, jeśli nie ma spacji; to po prostu znak nowej linii?
Ben

Jak pokazuje mój przykład, usuwana jest nawet tylko pusta linia (pierwsza linia). Dodałem więcej informacji, więc mam nadzieję, że to pomoże. :)
Sepero

3

Wolę używać egrep, chociaż w moim teście z oryginalnym plikiem z pustą linią twoje podejście działało dobrze (choć bez cudzysłowów w moim teście). To też zadziałało:

egrep -v "^(\r?\n)?$" filename.txt

Próbowałem tego. Nadal są wyświetlane puste linie. Czy może to być spowodowane tym, że plik został utworzony w systemie Windows?
węzeł ninja

3

Jeśli masz sekwencje wielu pustych wierszy w jednym rzędzie i chciałbyś mieć tylko jeden pusty wiersz na sekwencję, spróbuj

grep -v "unwantedThing" foo.txt | cat -s

cat -s pomija powtarzające się puste wiersze wyjściowe.

Twój wynik będzie pochodził z

match1



match2

do

match1

match2

Trzy puste wiersze w oryginalnym wyniku byłyby skompresowane lub „ściśnięte” w jeden pusty wiersz.


2
awk 'NF' file-with-blank-lines > file-with-no-blank-lines

2

To samo co poprzednie odpowiedzi:

grep -v -e '^$' foo.txt

Tutaj grep -eoznacza rozszerzoną wersję grep . „^ $” oznacza, że ​​nie ma żadnego znaku między ^ (początek wiersza) a $ (koniec wiersza). „^” i „$” to znaki wyrażenia regularnego.

Zatem polecenie grep -vwypisze wszystkie wiersze, które nie pasują do tego wzorca (brak znaków między ^ a $).

W ten sposób puste puste linie są eliminowane.


-enie oznacza "rozszerzonej wersji grepa", może jesteś zdezorientowany -E? Podręcznik wyraźnie mówi, że -epo prostu wyraźnie mówi, że następuje wzór. Ponieważ wzorzec nie zaczyna się od myślnika, a i tak definiujesz tylko jeden wzorzec, równie dobrze możesz go pominąć, ponieważ domyślnie grep oczekuje jednego wzorca wyrażenia regularnego: grep -v '^$' foo.txt(nie ma potrzeby korzystania z rozszerzonej funkcjonalności wyrażenia regularnego). Warto również wspomnieć, że nie eliminuje to pustych wierszy w pliku, a jedynie te, które są przesyłane potokiem przez wyjście. W takim przypadku sed -ibyłoby właściwym narzędziem.
Yeti

1

Bardzo się starałem, ale to wydaje się działać (zakładając, że \rcię tu gryzie):

printf "\r" | egrep -xv "[[:space:]]*"

To działa, jeśli zastąpię pierwszą część danymi wyjściowymi z pliku.
węzeł ninja

0

Korzystanie z Perla:

perl -ne 'print if /\S/'

\S oznacza dopasowywanie niepustych znaków.


0

egrep -v "^ \ s \ s +"

egrep już wykonuje regex, a \ s to biały znak.

Znak + powiela bieżący wzorzec.

^ Jest na początek


0

Posługiwać się:

grep pattern filename.txt | uniq

uniqzredukuje przylegające puste linie do jednej pustej linii, ale nie usuwa ich całkowicie. Mimo to lubię próbować tego używać uniq. Sortowanie w pierwszej kolejności skutecznie usunie wszystkie puste wiersze - pozostawiając tylko jeden, ale zmiana kolejności wierszy może być nie do przyjęcia.
Zach Young,

Słuszna uwaga. Spowoduje to również zgniatanie powtarzających się linii. Myślę, że moje rozwiązanie wprowadza błędy.
baitisj

0

Oto inny sposób na usunięcie białych linii i linii zaczynających się od #znaku. Myślę, że jest to przydatne do czytania plików konfiguracyjnych.

[root@localhost ~]# cat /etc/sudoers | egrep -v '^(#|$)'
Defaults    requiretty
Defaults   !visiblepw
Defaults    always_set_home
Defaults    env_reset
Defaults    env_keep =  "COLORS DISPLAY HOSTNAME HISTSIZE INPUTRC KDEDIR
LS_COLORS"
root    ALL=(ALL)       ALL
%wheel  ALL=(ALL)       ALL
stack ALL=(ALL) NOPASSWD: ALL

0

Prawdą jest, że użycie grep -v -e '^ $' może działać, jednak nie usuwa pustych wierszy, które mają 1 lub więcej spacji . Odkryłem, że najłatwiejszą i najprostszą odpowiedzią na usuwanie pustych linii jest użycie awk . Poniższy fragment jest nieco zmodyfikowany w stosunku do facetów z awk powyżej:

awk 'NF' foo.txt

Ale ponieważ to pytanie dotyczy używania grep, odpowiem na następujące pytanie:

grep -v '^ *$' foo.txt

Uwaga : spacja między ^ i *.

Lub możesz użyć \ s do oznaczenia pustej przestrzeni w następujący sposób:

grep -v '^\s*$' foo.txt
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.