Danek Duvall
Danek Duvall

Reputation: 377

how do I delete a regex-delimited range plus a few lines with sed?

I have a file containing a header I want to get rid of. I don't have a good way of addressing either the last line of the header or the first line of the data, but I can address the line before the next-to-last line of the header via a regular expression.

Example input:

a bunch of make output which I don't care about
for junk in blah; do
    can't check for done!
done
for test in blurfl; do # this is the addressable line
    more garbage
done
line 1
line 2
line 3
line 4
line 5

I've done the obvious 1,/for test in blurfl/d, but that doesn't get the next two lines. I can make the command {N;d} which gets rid of the next line, but {N;N;d} just blows away the rest of the file except the last line, which I figured out is because the range isn't slurped up and treated as a single entity, but instead is processed line-by-line.

I feel like I'm missing something obvious because I don't know some sed idiom, but none of the examples on the web or in the GNU manual have managed to trigger anything useful.

I can do this in awk, but other transformations I need to do make awk somewhat, well, awkward. But GNU sed is acceptable.

Upvotes: 0

Views: 44

Answers (2)

erik258
erik258

Reputation: 16305

I don't think you can do multi line matches in sed. First time I went down this rabbit hole I ended up using awk, which can support, but now recently I'd probably use Python or Ruby for this kind of thing.

Upvotes: 0

Craig Estey
Craig Estey

Reputation: 33601

I have to disagree about [not] using awk. Anything non-trivial is almost always easier in awk than sed [even the sed manpage says so]. Personally, I'd use perl, but ...

So, here's the awk script:

BEGIN {
    phase = 0
}

# initial match -- find second loop
phase == 0 {
    if ($0 ~ /for test in blurfl/) {
        phase = 1
        next
    }
}

# wait for end of second loop
phase == 1 {
    if ($0 ~ /done/) {
        phase = 2
        next
    }
}

# print phase
phase == 2 {
    print($0)
}

If you wish to torture yourself [and sed] for complex changes, well, caveat emptor, but don't say I didn't warn you ...

Upvotes: 2

Related Questions