Mert Nuhoglu
Mert Nuhoglu

Reputation: 10133

Match multiline and print it in perl regex

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

Answers (3)

Loic
Loic

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

Pedro Lobito
Pedro Lobito

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

choroba
choroba

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

Related Questions