et_phonehome
et_phonehome

Reputation: 137

Delimiter that may / may not span multiple lines using sed

I have pre-generated configuration files from a utility. How can I extract the parameter string which is delimited by '), that may or may not span multiple lines?

FILE1 can look like this - PARM3 spans multiple lines:

OPERAND      ID          = 'XXXX',
             ....
             PARM3       = ( 'VALUE3A',
                              ....
                             'VALUE3n'),
             PARM4       = ( 'VALUE4',
                              ....
                             'VALUE4n'),
                              ....

or FILE2 can look like this - PARM3 does not span multiple lines:

OPERAND      ID          = 'XXXX',
             ....
             PARM3       = ( 'VALUE3A'),
             PARM4       = ( 'VALUE4',
                              ....
                              'VALUE4n'),
             ....

For FILE1, the extract is good if the delimiter '), is on another line:

sed -n "/.* PARM3 .*/,/')\,/p" FILE1

Output:

  PARM3       = ( 'VALUE3A',
                  ....
                  'VALUE3n'),

For FILE2, the extract does not work if the delimiter '), is on the same line:

sed -n "/.* PARM3 .*/,/')\,/p" FILE2

Output:

        PARM3       = ( 'VALUE3A'),
        PARM4       = ( 'VALUE4',
                         ....
                        'VALUE4n'),

How can I fix this sed statement using sed only to handle the delimiter which may or may not be on the same line?

Upvotes: 1

Views: 56

Answers (3)

anubhava
anubhava

Reputation: 785651

You may use this gnu-awk command that uses a custom RS:

awk -v RS='[[:blank:]]*PARM3[[:blank:]]*=[[:blank:]]*\\([^)]*\\),[[:blank:]]*' 'RT{print RT}' file

For file1 it gives:

     PARM3       = ( 'VALUE3A',
                      ....
                     'VALUE3n'),

For file2 it gives:

    PARM3       = ( 'VALUE3A'),

Upvotes: 1

Casimir et Hippolyte
Casimir et Hippolyte

Reputation: 89584

[EDIT]more simple:

sed -n '/PARM3/,/)/{p;/)/q}' file

a way with sed:

sed -n '/PARM3/{:a;/)/{p;q};N;ba}' file

details:

/PARM3/ {     # if PARM3 is found
    :a            # define a label "a"
    /)/ {         # if ) is found
        p             # print the pattern space
        q             # quit
    }
    N             # append the next line to the pattern space
    ba            # go to label a
}

Upvotes: 1

Benjamin W.
Benjamin W.

Reputation: 52381

If you have GNU grep, you could use its -z option to treat the complete input as a single line:

$ grep -Ezo '\s+PARM3\s+=\s+\([^)]*\)' FILE2

             PARM3       = ( 'VALUE3A',
                              ....
                             'VALUE3n')

-o retains nothing but the match, and -E enables extended regular expressions.

The regex searches for PARM3 = surrounded by an arbitrary number of blanks, followed by ( and then everything up to and including the closing ). To avoid greedy matching, I use [^)] ("not a closing parenthesis").

If you don't need the leading blanks, they can be skipped, and if you need the trailing comma, it can be added (optional, in case it's not there):

$ grep -Ezo 'PARM3\s+=\s+\([^)]*\),?' infile
PARM3       = ( 'VALUE3A',
                              ....
                             'VALUE3n'),

or to get proper alignment, but not the newline preceding the match:

$ grep -Ezo '[[:blank:]]*PARM3\s+=\s+\([^)]*\),?' infile
             PARM3       = ( 'VALUE3A',
                              ....
                             'VALUE3n'),

Upvotes: 0

Related Questions