Jak podać wzór nowej linii w grep?


98

Jak podać wzór nowej linii w grep? Nowa linia na początku, nowa linia na końcu. Nie sposób wyrażeń regularnych. Coś w rodzaju \ n.


6
Nie jest jasne, czego chcesz. new line at the beginningjest pustą linią i new line at endma zastosowanie do każdej linii w pliku. Czy możesz zamieścić przykład?
PP,

3
Właściwie możesz po prostu użyć $. Jest nieco ograniczona, ale nadaje się do użytku w prostych przypadkach.
Krzysztof Jabłoński

Odpowiedzi:


86

grep wzorce są dopasowywane do poszczególnych wierszy, więc nie ma możliwości dopasowania wzorca do nowej linii znalezionej w danych wejściowych.

Możesz jednak znaleźć puste wiersze w ten sposób:

grep '^$' file
grep '^[[:space:]]*$' file # include white spaces 

Przynajmniej GNU grep ma opcję -z, która sprawia, że ​​grep łamie linie za pomocą znaku null. Jednak wydaje się, że nie obsługuje nowej linii lub \ n we wzorcu, aby dopasować nową linię, zobacz raport o błędzie .
jarno

1
@jarno Obsługuje \ nw wzorach z flagą -P
rubystallion

92

spróbuj pcregrepzamiast zwykłego grep:

pcregrep -M "pattern1.*\n.*pattern2" filename

ta -Mopcja umożliwia dopasowanie w wielu wierszach, więc możesz wyszukiwać nowe wiersze jako \n.


23

Dzięki @jarno wiem o opcji -z i dowiedziałem się, że używając GNU grep z opcją -P, dopasowanie do \njest możliwe . :)

Przykład:

grep -zoP 'foo\n\K.*'<<<$'foo\nbar'

Wydruki bar


1
Świetnie, zwróć uwagę, że nie dostaję powiadomienia o „@jarno” w odpowiedzi.
jarno

3
To jest świetne! Dziękuję bardzo za udostępnienie!
Alicia Tang,

Pracuje dla mnie. Wielkie dzięki. grep -zoPnir "dex\n035" ./dir/
galian

22

Możesz użyć w ten sposób ...

grep -P '^\s$' file
  • -Pjest używany dla wyrażeń regularnych Perla (rozszerzenie POSIX grep).
  • \sdopasuj białe znaki; jeśli występuje po nim *, dopasowuje również pusty wiersz.
  • ^dopasowuje początek wiersza. $dopasowuje koniec linii.

2
-Pjest rozszerzeniem GNU. Mogę go używać, gdy sytuacja tego wymaga (zwykle lookahead / lookbehind), ale POSIX grep może to zrobić tylko z plikiem [[:space:]].
jordanm

1
Strony podręcznika grep FWIW, Solaris i BSD (nie sprawdzały innych), oba mają akapit dla -P. GNU i tak jest dość standardowe. :)
K3 --- rnc

1
Ze strony podręcznika: [-P] Ta opcja nie jest obsługiwana we FreeBSD.
Marián Černý

Nie [-P] dla MacOsX albo: grep [-abcdDEFGHhIiJLlmnOopqRSsUVvwxZ] [-A num] [-B num] [-C [num]] [-e wzorzec] [-f plik] [--binary-files = wartość] [--color [= kiedy]] [--colour [= kiedy]] [--context [= num]] [--label] [--line-buffered] [--null] [wzorzec] [plik. ..]
Niccolò,

@ Niccolò Będziesz chciał brew install grepzdobyć GNU grep, który jest lepszy pod wieloma względami. apple.stackexchange.com/questions/193288/…
herdrick

6

Jeśli chodzi o obejście problemu (bez używania nieprzenośnego -P), możesz tymczasowo zastąpić znak nowego wiersza innym i zmienić go z powrotem, np:

grep -o "_foo_" <(paste -sd_ file) | tr -d '_'

Zasadniczo szuka dokładnego dopasowania, _foo_gdzie _oznacza \n(więc __= \n\n). Nie musisz go tłumaczyć z powrotem tr '_' '\n', ponieważ każdy wzór i tak zostałby wydrukowany w nowej linii, więc _wystarczy usunąć .


przepraszam za moją ignorancję, ale czy użycie podstawienia procesu nie jest kolejną funkcją niezgodną z POSIX, a więc nieprzenośną? w powłoce posix nie mogłem zrobić <(p paste -sd_ file )?
humanityANDpeace

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.