tags:

views:

991

answers:

5

I have the following sequence occurring multiple times in a file:

yyyy
xxxx
zzzz

I have a regex that matches xxxx. Whenever there is a match, I want to delete that line, the line before (e.g. yyyy) and the line after it (e.g. zzzz). How can I use sed to do this?

+2  A: 

This is how I would do it in perl maybe it can help send you on the right track... Good luck!

open(INFILE,"<in.txt");
my(@arrayOutBoundData, $skipNextLine)l
for (<INFILE>) {
    if (not $skipNextLine) {
     if (/^xxxx$/) {
      pop(@arrayOutBoundData);
      $skipNextLine = 1;
     } else {
      push(@arrayOutBoundData,$_);
     }
    }
$skipNextLine = 0
}

open(OUTFILE,">out.txt");
for (@arrayOutBoundData) {
    print OUTFILE;
}

(Not tested no perl on this system please forgive any over site.)

Copas
+1  A: 

I don't know sed but with Perl the regex would become something like

$replaced =~ s/^.*\r\n(^xxxx)\r\n^.*/$1/mg;

// ^.*\r\n(^xxxx)\r\n^.*
// 
// Options: ^ and $ match at line breaks
// 
// Assert position at the beginning of a line (at beginning of the string or after a line break character) «^»
// Match any single character that is not a line break character «.*»
//    Between zero and unlimited times, as many times as possible, giving back as needed (greedy) «*»
// Match a carriage return character «\r»
// Match a line feed character «\n»
// Match the regular expression below and capture its match into backreference number 1 «(^xxxx)»
//    Assert position at the beginning of a line (at beginning of the string or after a line break character) «^»
//    Match the characters “xxxx” literally «xxxx»
// Match a carriage return character «\r»
// Match a line feed character «\n»
// Assert position at the beginning of a line (at beginning of the string or after a line break character) «^»
// Match any single character that is not a line break character «.*»
//    Between zero and unlimited times, as many times as possible, giving back as needed (greedy) «*»
Lieven
+1  A: 

You can check out this document. It covers using sed to work with multiple lines.

kender
+3  A: 

The trick is to store the last line seen in the "hold space".

sed -n '
/^xxxx/{n
        n
        x
        d
       }
x
1d
p
${x
  p
 }
' <input file>

Starting with the x - swap the current input line with the hold space (x), then for the first line don't print anything (1d), subsequent lines print the line just swapped from the hold space (p), on the last line swap the hold space again and print what was in it ($x{x p}. That leaves what to do when we hit the target line (starting /^xxxx/) - read the next two lines into the pattern space (n n) and swap the pattern space with the hold space (x) - this leaves the hold space with next line we want to print and the pattern space with the line before the match, which we don't want, so we ditch it (d)

Beano
A further explanation of the 'x' command which "eXchanges" the pattern space with the hold buffer: http://www.grymoire.com/Unix/Sed.html#uh-53
Ben Lever
A: 
grep -v -f <(grep -1 "xxxx" file) file