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.

tuxnani
źródło
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 
arash kordi
źródło
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.

zerowa rewolucja
źródło
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

rubystallion
źródło
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.
Manikandan Rajendran
źródło
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ąć .

kenorb
źródło
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
2

właśnie znalazłem

grep $'\r'

Używa $'\r'do ucieczki w stylu c w Bash.

w tym artykule

HHHartmann
źródło