5

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:

  • tail -n +731 file|sed '/some_pattern/d' >> file
  • manually remove edited range in file from previous step

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

Community
  • 1
  • 1
ks1322
  • 33,961
  • 14
  • 109
  • 164

4 Answers4

11

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 
sat
  • 14,589
  • 7
  • 46
  • 65
5

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 '' ...)

cuonglm
  • 2,766
  • 1
  • 22
  • 33
1

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.

Ed Morton
  • 188,023
  • 17
  • 78
  • 185
0

awk to the rescue!

awk '!(NR>=731 && /pattern/)' input > output
karakfa
  • 66,216
  • 7
  • 41
  • 56