Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Regex with sed, search across multiple lines

Tags:

regex

unix

sed

I'd like to concatenate a few lines, perform a regex match on them and print them. I tried to do that with sed.

Namely, I used:

cat add | sed -rn '/FIRST_LINE_REGEX/,/LAST_LINE_REGEX/s/SOME_REGEX/&/p'

It prints only the lines that match SOME_REGEX while I expect it to concatenate the lines from the range between FIRST_LINE and LAST_LINE and print the concatenation if it matches SOME_REGEX.

like image 795
Marcin Król Avatar asked Aug 04 '13 18:08

Marcin Król


People also ask

Can sed work on multiple lines?

By using N and D commands, sed can apply regular expressions on multiple lines (that is, multiple lines are stored in the pattern space, and the regular expression works on it): $ cat two-cities-dup2.

Which flag will search over multiple lines?

The m flag indicates that a multiline input string should be treated as multiple lines. For example, if m is used, ^ and $ change from matching at only the start or end of the entire string to the start or end of any line within the string.

What is regex multiline?

Multiline option, or the m inline option, enables the regular expression engine to handle an input string that consists of multiple lines. It changes the interpretation of the ^ and $ language elements so that they match the beginning and end of a line, instead of the beginning and end of the input string.


1 Answers

When using '/FIRST_LINE_REGEX/,/LAST_LINE_REGEX/' each line is still processed separately, to concatenate lines you need to use the hold space or the N command to append the next line to the pattern space. Here is one option:

cat add | sed -rn '/FIRST_LINE_REGEX/{:a;N;/LAST_LINE_REGEX/{/SOME_REGEX/p;d};ba}'

Commented version:

cat add | sed -rn '/FIRST_LINE_REGEX/ {  # if line matches /FIRST_LINE_REGEX/
  :a                                       # create label a
  N                                        # read next line into pattern space
  /LAST_LINE_REGEX/ {                      # if line matches /LAST_LINE_REGEX/
    /SOME_REGEX/p                            # print if line matches /SOME_REGEX/
    d                                        # return to start
  }
  ba                                       # return to label a
}'
like image 68
Andrew Clark Avatar answered Sep 28 '22 17:09

Andrew Clark