3

How do I delete a line only if it is at a specified line number and it matches the pattern?


For example:

  • I want to delete (d);
  • the third line (3);
  • if it's blank (^$);

The following syntax:

cat file | sed '3 /^$/d'

Returns the following error:

sed: -e expression #1, char 3: unknown command: `/'
voices
  • 1,252
  • 3
  • 15
  • 30
user123456
  • 4,758
  • 11
  • 52
  • 78
  • 2
    Don't you mean **third** line if it is blank? – Kaz Oct 03 '16 at 03:14
  • 1
    What's the special use of `cat` in your example? Any reason to complicate things and not run `sed '3 /^$/d' file`? – Anthon Oct 03 '16 at 06:35
  • Like Kaz, I'm puzzled by the code, given the stated interest in deleting the *first* line. Pretty clearly, though, the [code is pointing to line 3](http://www.grymoire.com/Unix/Sed.html#toc-uh-26). – Dɑvïd Oct 03 '16 at 08:05
  • 1
    I may be blind but I don't see how the answers to the linked question really showing how to combine both a line number match and a pattern match. The closest is this: `sed -i '4s/foo/bar/g' file` (substitute only on one line), but that only works since `s///` is an operation, and a no-op if it doesn't match. (So yah, voted for reopen) – ilkkachu Oct 03 '16 at 12:13
  • 1
    FWIW, I voted to close this question as *unclear* due to the confusion over which line should be deleted (my vote was lumped in with the duplicate votes). Since tjt263's edit removes the ambiguity, I'm now voting to re-open. – Anthony Geoghegan Oct 03 '16 at 14:02

2 Answers2

10

Try doing this:

sed '3{/^$/d;}' file

Note the braces.

Stéphane Chazelas
  • 522,931
  • 91
  • 1,010
  • 1,501
user000001
  • 3,347
  • 19
  • 30
  • 10
    Since this answer currently contains _no_ explanation what-so-ever: Both line numbers (the `3`) and patterns (the `/^$/`) are ways of specifying how to match lines: each command can only be preceded by one way of matching. Fortunately, brackets create a group of commands that can go anywhere a single command can go. So you can do `42 { /regex/ d }`, or `/regex/ { 42 d }`, or nest them for more complex situations: `/foo/ { 1 { /bar/ d }; $ { /qux/ d } }` – mtraceur Oct 02 '16 at 16:38
  • Thanks. I didn't know you could use the braces like that. – voices Oct 03 '16 at 11:04
3

Like user000001 answered, sed '3{/^$/d;}' file is good enough, but it will only show you that output. If you want to modify the file, and your sed is the GNU sed, you can use sed -i '3{/^$/d}' file (for GNU sed, the ; before } can also be omitted here).

`-i[SUFFIX]'
`--in-place[=SUFFIX]'
     This option specifies that files are to be edited in-place.  GNU
     `sed' does this by creating a temporary file and sending output to
     this file rather than to the standard output.(1).

With FreeBSD/OS/X sed, use sed -i '' '3{/^$/d;}' file.

Stéphane Chazelas
  • 522,931
  • 91
  • 1,010
  • 1,501
Jaur
  • 344
  • 1
  • 4