Solution for How to delete 2 consecutive lines only when both patterns are matched
is Given Below:
Let’s consider this simple file:
{
bla bla
bla bla bla
}
{
bla bla
bla bla bla
}
bla bla
bla bla bla
I need to remove only those consecutive lines:
}
{
The result should be:
{
bla bla
bla bla bla
bla bla
bla bla bla
}
bla bla
bla bla bla
I tried the following:
sed -e '/^}$/,/^{$/d' file
Unfortunately, the last closing curly brace and remaining lines have been removed:
{
bla bla
bla bla bla
bla bla
bla bla bla
Any suggestion?
I’m open to any simple solution involving other tools such as awk/perl/… if necessary.
You may use this sed
:
sed '/^}$/ { N; /n{$/ d; }' file
{
bla bla
bla bla bla
bla bla
bla bla bla
}
bla bla
bla bla bla
To save changes inline:
sed -i.bak '/^}$/ { N; /n{$/ d; }' file
Alternatively this awk
would also work:
awk '/^}$/ {p = $0; next} p != "" {if (/^{$/) {p=""; next} $0 = p ORS $0; p = ""} 1' file
{
bla bla
bla bla bla
bla bla
bla bla bla
}
bla bla
bla bla bla
Perl solution:
perl -lne 'undef $prev, next if $prev eq "}" && $_ eq "{";
print $prev if defined $prev;
$prev = $_;
END { print $prev if defined $prev}' -- file
-n
reads the input line by line and runs the code for each line.-l
removes newlines from input and adds them toprint
.- We store the previous line in
$prev
. If the previous line was}
and the current line is{
, we forget the previous line and read the next line. Otherwise, we print the previous line if there was any (which means we don’t print an empty line after the forgotten line). Then we store the current line to $prev and repeat. - The
END
part is needed to print the last remembered line, if any.
With GNU sed for -z
:
$ sed -z 's/}n{n//' file
{
bla bla
bla bla bla
bla bla
bla bla bla
}
bla bla
bla bla bla
With GNU awk for multi-char RS:
$ awk -v RS='}n{n' -v ORS= '1' file
{
bla bla
bla bla bla
bla bla
bla bla bla
}
bla bla
bla bla bla
$ sed '$!N;/^}n{$/d;P;D' file
{
bla bla
bla bla bla
bla bla
bla bla bla
}
bla bla
bla bla bla
This two line buffer will also work for other input as in the following test:
$ cat test
}
}
{
foo
}
$ sed '$!N;/^}n{$/d;P;D' test
}
foo
}
Also you may use this awk
:
awk 'BEGIN{RS="";FS=OFS="n"}{print $1,$2,$3,$6,$7,$8,$9,$10}' file
{
bla bla
bla bla bla
bla bla
bla bla bla
}
bla bla
bla bla bla
Or using for
loop:
awk 'BEGIN{RS="";FS=OFS="n"}{
for(i=1;i<=NF;i++) {
if(i == 4 || i == 5) continue; print $i}
}' file
{
bla bla
bla bla bla
bla bla
bla bla bla
}
bla bla
bla bla bla