How to give a pattern for new line in grep?
Asked Answered
A

6

140

How to give a pattern for new line in grep? New line at beginning, new line at end. Not the regular expression way. Something like \n.

Anjanetteanjela answered 29/9, 2012 at 12:6 Comment(3)
It's not clear what you want. new line at the beginning is a blank line and new line at end applies to every line in the file. Can you post an example?Sequent
Actually you can just use $. It's somewhat limited, but usable in simple cases.Armenta
gnu.org/software/grep/manual/grep.html#Usage see item 15.Despite
G
109

grep patterns are matched against individual lines so there is no way for a pattern to match a newline found in the input.

However you can find empty lines like this:

grep '^$' file
grep '^[[:space:]]*$' file # include white spaces 
Gog answered 29/9, 2012 at 12:23 Comment(2)
At least GNU grep has -z option that makes grep break lines by null character. However, it does not seem to support newline or \n in pattern to match newline, see bug report.Despite
@Despite It supports \n in patterns with the -P flagMonas
W
114

try pcregrep instead of regular grep:

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

the -M option allows it to match across multiple lines, so you can search for newlines as \n.

Wilkerson answered 1/10, 2012 at 17:46 Comment(2)
This is an excellent suggestion. I've used pcregrep a LOT the last week. For example, pcregrep -lMr "\r\n" * to recursively find all files that have at least one CRLF line ending. And after conversion to Unix line endings, I used pcregrep -lMr " \n" * to find all files having Markdown soft line breaks. Very helpful!Gynous
This is the most efficient of all the answers, trying to accomplish this with grep made me waste a day.Inflectional
G
109

grep patterns are matched against individual lines so there is no way for a pattern to match a newline found in the input.

However you can find empty lines like this:

grep '^$' file
grep '^[[:space:]]*$' file # include white spaces 
Gog answered 29/9, 2012 at 12:23 Comment(2)
At least GNU grep has -z option that makes grep break lines by null character. However, it does not seem to support newline or \n in pattern to match newline, see bug report.Despite
@Despite It supports \n in patterns with the -P flagMonas
M
45

Thanks to @jarno I know about the -z option and I found out that when using GNU grep with the -P option, matching against \n is possible. :)

Example:

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

Result:

bar

Example that involves matching everything including newlines:

.* will not match newlines. To match everything including newlines, use1 (.|\n)*:

grep -zoP 'foo\n\K(.|\n)*'<<<$'foo\nbar\nqux'

Result:

bar
qux

1 Seen here: https://stackoverflow.com/a/33418344

Monas answered 9/3, 2018 at 11:10 Comment(3)
Great, note that I do not get notification about the "@jarno" in the answer.Despite
This is great! Thank you so much for sharing!Bysshe
Works for me. Thanks a lot. grep -zoPnir "dex\n035" ./dir/Ferrigno
L
28

You can use this way...

grep -P '^\s$' file
  • -P is used for Perl regular expressions (an extension to POSIX grep).
  • \s match the white space characters; if followed by *, it matches an empty line also.
  • ^ matches the beginning of the line. $ matches the end of the line.
Lulu answered 29/9, 2012 at 12:30 Comment(5)
-P is a GNU extension. I am fine for using it when the situation calls for it (typically lookahead/lookbehind), but POSIX grep can do this just file with [[:space:]].Dyeline
FWIW, Solaris' and BSD's grep manpages (didn't check others) both have a paragraph for -P. GNU is quite standard anyway. :)Scenography
From manual page: [-P] This option is not supported in FreeBSD.Poddy
No [-P] for MacOsX either: grep [-abcdDEFGHhIiJLlmnOopqRSsUVvwxZ] [-A num] [-B num] [-C[num]] [-e pattern] [-f file] [--binary-files=value] [--color[=when]] [--colour[=when]] [--context[=num]] [--label] [--line-buffered] [--null] [pattern] [file ...]Habiliment
@Niccolò You'll want to brew install grep to get GNU grep, which is superior in several ways. apple.stackexchange.com/questions/193288/…Gilbertogilbertson
P
8

As for the workaround (without using non-portable -P), you can temporary replace a new-line character with the different one and change it back, e.g.:

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

Basically it's looking for exact match _foo_ where _ means \n (so __ = \n\n). You don't have to translate it back by tr '_' '\n', as each pattern would be printed in the new line anyway, so removing _ is enough.

Papandreou answered 18/10, 2015 at 12:4 Comment(1)
pardon my ignorance, but is using process substituion not yet another NON posix compatible, hence non-portable feature? in posix shell I could not do <(p paste -sd_ file )?Rafaello
B
7

just found

grep $'\r'

It's using $'\r' for c-style escape in Bash.

in this article

Butane answered 29/12, 2018 at 10:21 Comment(1)
carriage return \r is not a newline \n. If your grepping for windows style line ending you need \r\nSpermatic

© 2022 - 2024 — McMap. All rights reserved.