Searching for multiple lines including a blank one

2019-08-26 01:55发布

问题:

I am using the following command to find a pattern spanning multiple lines and replacing it with a blank line:

sed -n '1h; 1!H; ${ g; s/<Pattern1>\n<pattern2> //g p }' <file-name>

For example, to find the pattern John Doe

in a file test.txt which contains the following entries:

Mary

John
Doe
Simon
Henry

I would use the command:

sed -n  '1h; 1!H; ${ g; s/John\nDoe //g p }' test.txt

However, I can't seem to make this command work for a pattern which has the second line as a blank, i.e. using the ^$ character.

Thus, if I were to search for the multi-line pattern, Mary followed by a blank line, I do not see any matching patterns. Thus, the following command causes no searches and thus no substitutions.

sed -n  '1h; 1!H; ${ g; s/Mary\n^$ //g p }' test.txt

Any thoughts?

EDIT


However, if I store multiple such command in a file and execute them, then the first search goes through fine, however on searching for subsequent patterns, I get a blank output from sed.

That is if I store, sed -n '1h; 1!H; ${ g; s/\n //g p }' sed -n '1h; 1!H; ${ g; s/\n //g p }' in a file and then execute each line in the this file using the eval keyword, then the first sed replaces the first multi-line patterns, i.e. pattern1, followed by pattern2, however, it returns a blank output even though the file contains these patterns. Any clues?

回答1:

This works for me with your input file:

sed -n  '1h; 1!H; ${ g; s/Mary\n\n/\n/g p }'

Explanation:

Mary\n\n                # Mary with two consecutive newlines, the first one is automatically added by
                        # the 'H' command, and the next one means the empty line, asumming it has no
                        # spaces.
\n                      # Substitute it with a blank line.


回答2:

This might work for you:

sed '$!N;s/John\nDoe//;P;D' file
Mary


Simon
Henry
sed '$!N;s/Mary\n$//;P;D' file

John
Doe
Simon
Henry

N.B. ^ refers to the start of the string not the beginning of a line (unless in GNU sed you use the m flag). Likewise $ means the end of the string.

EDIT:

The above two commands can be combined:

sed '$!N;s/John\nDoe//;s/Mary\n$//;P;D' file


Simon
Henry