118

I have a file which is made up of several lines of text:

The first line
The second line
The third line
The fourth line

I have a string which is one of the lines: The second line

I want to delete the string and all lines after it in the file, so it will delete The third line and The fourth line in addition to the string. The file would become:

The first line

I've searched for a solution on google, and it seems that I should use sed. Something like:

sed 'linenum,$d' file

But how to find the line number of the string? Or, how else should I do it?

Shawn Chin
  • 84,080
  • 19
  • 162
  • 191
DocWiki
  • 3,488
  • 10
  • 39
  • 49
  • 2
    Your problem statement is contradictory: 'I want to delete all lines **after** the line' means you delete just two lines (as you say), but then your example output shows the match line as missing too. Which do you actually want? – Jonathan Leffler Mar 08 '11 at 01:58
  • The matching line AND the all the lines after it. I should improve my English. Thanks for your information. – DocWiki Mar 08 '11 at 19:24
  • related https://stackoverflow.com/questions/17364951/remove-all-lines-before-a-match-with-sed – Trevor Boyd Smith Apr 24 '19 at 16:49
  • If I don't want to delete the line I search, then how to make it? – byhuang1998 Dec 10 '20 at 02:46

6 Answers6

194

If you don't want to print the matched line (or any following lines):

sed -n '/The second line/q;p' inputfile

This says "when you reach the line that matches the pattern quit, otherwise print each line". The -n option prevents implicit printing and the p command is required to explicitly print lines.

or

sed '/The second line/,$d' inputfile

This says "delete all lines from the output starting at the matched line and continuing to the end of the file".

but the first one is faster. However it will quit processing completely so if you have multiple files as arguments, the ones after the first matching file won't be processed. In this case, the delete form is better.

If you do want to print the matched line, but not any following lines:

sed '/The second line/q' inputfile

This says "print all lines and quit when the matched line is reached" (the -n option (no implicit print) is not used).

See man sed for additional information.

Dennis Williamson
  • 346,391
  • 90
  • 374
  • 439
  • 3
    But some commands get antsy about broken pipes (RCS `co -p` for example), and then you are better off with the `sed '/The second line/,$d'` notation. – Jonathan Leffler Mar 08 '11 at 01:56
  • Can you please add explanations? – Ahmad Abdelghany Jun 01 '17 at 14:00
  • @AhmadAbdelghany: Explanations added. – Dennis Williamson Jun 01 '17 at 16:10
  • @DennisWilliamson Thanks a lot. – Ahmad Abdelghany Jun 02 '17 at 08:52
  • the first method print out the last line before matched line twice. deleting the `p` after `;` works. – CrazyFrog Sep 29 '17 at 22:06
  • @CrazyFrog: No. It doesn't. If you remove the `p`, _nothing_ gets printed. Note the `-n`. – Dennis Williamson Sep 29 '17 at 22:47
  • If several files are given as an argument, e.g. to substitute in place with the -i argument, only the first file is modified. I think it might be worth mentioning it - it surely would have been good to know for me. – Ferdinando Randisi Jan 25 '18 at 15:04
  • @FerdinandoRandisi: If you use the `q` (quit) command, `sed` is going to quit altogether, not just for that file. The `d` form will allow processing to continue to the next file. I'll add that information to my answer. – Dennis Williamson Jan 25 '18 at 18:18
  • I had to add -nr for regex to match any amount of spaces in the line I wanted to match. – Brian Wiley Jul 19 '20 at 02:23
  • @BrianWiley: There must have been more to it since neither of those options have an effect like you describe without also changing the regex. The `-n` option wouldn't be involved at all (it disables automatic output) and the `-r` (or `-E`) option enables enhanced regexes but doesn't otherwise do anything. – Dennis Williamson Jun 28 '22 at 16:33
  • When I turn `The second line` into a variable in `sed "/$match/,$d" inputfile`, the expected effect cannot be achieved. Do I need to treat commas specially? – moluzhui Jun 15 '23 at 11:00
  • 1
    @moluzhui: When you changed the quotes from single to double so the `$match` variable can be evaluated it made the sequence `$d` appear to also be a variable which likely evaluates to an empty string or some arbitrary residual value. Escaping that dollar sign should make it work again: `sed "/$match/,\$d" inputfile`. The comma doesn't change its meaning. It's an address separator. – Dennis Williamson Jun 15 '23 at 11:32
43

This is a bit shorter than other given solutions. Quit using capital Q avoids printing the current line.

 sed '/The second line/Q' file

To actually delete the lines you can use the same syntax.

 sed -i '/The second line/Q' file
jaap
  • 5,661
  • 2
  • 20
  • 25
6
sed '/The second line/q0' file

Or, without gnu sed:

sed '/The second line/q' file

Or, using grep:

grep -B 9999999 "The second line"
Erik
  • 88,732
  • 13
  • 198
  • 189
6

Using awk (not showing the matched line)

awk '/pattern/ {exit} {print}' file.txt
Joel Arnold
  • 1,201
  • 13
  • 28
2

First add the line number and delete the line

cat new.txt 
The first line
The second line
The third line
The fourth line

 cat new.txt  | nl
     1  The first line
     2  The second line
     3  The third line
     4  The fourth line



cat new.txt  | nl | sed  "/2/d"
     1  The first line
     3  The third line
     4  The fourth line

cat new.txt  |  nl |sed  "3d;4d"
     1  The first line
     2  The second line

using awk

awk 'NR!=3 && NR!=4' new.txt 
The first line
The second line
sush
  • 5,897
  • 5
  • 30
  • 39
1
awk '/The second line/{exit}1' file
kurumi
  • 25,121
  • 5
  • 44
  • 52