ks1322
ks1322

Reputation: 35716

Delete lines by pattern in specific range of lines

I want to remove lines from file by regex pattern using sed just like in this question Delete lines in a text file that containing a specific string, but only inside a range of lines (not in the whole file). I want to do it starting from some line number till the end of file.

This is how I've done it in combination with tail:

Is there a shorter way to do it with sed only?
Something like sed -i '731,1000/some_pattern/d' file?

Upvotes: 6

Views: 5124

Answers (4)

cuonglm
cuonglm

Reputation: 2816

You need $ address to match end of file. With GNU sed:

sed -i '731,${/some_pattern/d;}' file

Note that this can be slower than tail -n +number, because sed will start processing at start of file instead of doing lseek() like tail.

(With BSD sed you need sed -i '' ...)

Upvotes: 6

Ed Morton
Ed Morton

Reputation: 203597

sed is for simple substitutions on individual lines, that is all. For anything even marginally more interesting an awk solution will be clearer, more robust, portable, maintainable, extensible and better in just about ever other desirable attribute of software.

Given this sample input file:

$ cat file
1
2
3
4
1
2
3
4
1
2
3
4

The following script will print every line except a line containing the number 3 that occurs after the 6th line of the input file:

$ awk '!(NR>6 && /3/)' file
1
2
3
4
1
2
4
1
2
4

Want to only do the deletion between lines 6 and 10? No problem:

$ awk '!(NR>6 && NR<10 && /3/)' file
1
2
3
4
1
2
4
1
2
3
4

Want the skipped lines written to a log file? No problem:

awk 'NR>6 && /3/{print > "log";next} {print}' file

Written to stderr?

awk 'NR>6 && /3/{print | "cat>&2";next} {print}' file

Want a count of how many lines you deleted also written to stderr?

awk 'NR>6 && /3/{print | "cat>&2"; cnt++; next} {print} END{print cnt | "cat>&2"}' file

ANYTHING you want to do additionally or differently will be easy and build on what you start with. Try doing any of the above, or just about anything else, with a sed script that satisfies your original requirement.

Upvotes: 2

karakfa
karakfa

Reputation: 67507

awk to the rescue!

awk '!(NR>=731 && /pattern/)' input > output

Upvotes: 0

sat
sat

Reputation: 14949

You can use this sed,

sed -i.bak '731,1000{/some_pattern/d}' yourfile

Test:

$ cat a
1
2
3
13
23
4
5

$ sed '2,4{/3/d}' a
1
2
23
4
5 

Upvotes: 12

Related Questions