Reputation: 10133
I want to match a multiline regex and print only the lines that match:
$ cat test.txt
line1
line2
line3
$ perl -ne 'print if /line2.line3/s' test.txt
$
This regex actually matches line2\nline3
but it is not printed. regex101 verifies that it is matched.
Using command switch 0777
prints the lines that match but then it prints non-matched lines too:
$ perl -0777 -ne 'print if /line2.line3/s' test.txt
line1
line2
line3
Using 0777
in a substitution regex works as expected:
$ perl -0777 -pe 's/line2.line3/replaced/s' test.txt
line1
replaced
I would like to learn if it is possible to print only lines that match a multiline regex?
Upvotes: 5
Views: 3603
Reputation: 650
Another variant considering the end of the lines could be:
perl -0777 -ne '($,, $\) = ("\n")x2; print /(^line2$)\s(^line3$)/msg'
Comparison:
$ cat test.txt
line1
line2
line3
line1
line2 line3
$ perl -0777 -ne 'print /line2\sline3\s/sg' test.txt
line2
line3
line2 line3
$ perl -0777 -ne '($,, $\) = ("\n")x2; print /(^line2$)\s(^line3$)/gms' test.txt
line2
line3
The m
modifier allows for using ^
and $
in a multiline context. The g
modifier makes the regex loop over the string. The s
modifier is not needed in this case, but some prefer to always have it. The groups makes the list the regex evaluates to return two items per match. Finally, the values print uses for list separators ($,
) and for the end of the list ($\
), have to be set to "\n"
.
Version arguably simpler/better and closer to the solution above:
perl -0777 -ne 'print /line2\nline3\n/sg' test.txt
Upvotes: 0
Reputation: 98901
I guess you don't need if
, while
or regex groups.
perl -0777 -ne 'print /line2\sline3\s/sg' test.txt
Output:
line2
line3
Regex Explanation:
line2\sline3\s
--------------
Match the character string “line2” literally (case insensitive) «line2»
Match a single character that is a “whitespace character” (any Unicode separator, tab, line feed, carriage return, vertical tab, form feed, next line) «\s»
Match the character string “line3” literally (case insensitive) «line3»
Match a single character that is a “whitespace character” (any Unicode separator, tab, line feed, carriage return, vertical tab, form feed, next line) «\s»
Upvotes: 3
Reputation: 241828
print
without an argument prints $_
. If you use -0777
, the whole file is read into $_
, so if there is a match, you print the whole file. If you only want to show the matching parts, you can use
perl -0777 -ne 'print "$1\n" while /(line2.line3)/sg' test.txt
Upvotes: 8