How to delete 2 consecutive lines only when both patterns are matched

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.

Upvotes: 1

Views: 286

Answers (5)

Carlos Pascual
Carlos Pascual

Reputation: 1126

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

Upvotes: 0

Ed Morton
Ed Morton

Reputation: 203512

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

Upvotes: 2

user14473238
user14473238

Reputation:

$ 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
}

Upvotes: 1

anubhava
anubhava

Reputation: 785146

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

Upvotes: 4

choroba
choroba

Reputation: 241868

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 to print.
  • 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.

Upvotes: 3

Related Questions