I'm trying to add three hyphens to the first empty line of a given text file, and am trying to use sed for this. My initial file (a MultiMarkdown file) looks something like this:

title: "Ch. 1: Unparticipated Causality"
author: Jonathan Greig
biblio-files: bibliography.bib
biblio-style: chicago-authordate
mainfont: Linux Libertine O
linestretch: 1.5
documentclass: article
geometry: margin=1in
citecolor: black
linkcolor: black

## Ch 1: Unparticipated Causality ##

In between linkcolor: black and ## Ch 1 ... ##, I'm trying to append a few dashes (---). Not quite sure how to accomplish this---the following command hasn't given for me:

sed '/^$/a ---' Chapter1Rev4.md

Currently the result is "command a expects \ followed by text", and not sure how to add the backslash or how to escape the hyphens/dashes.


4 Answers 4

{ sed -e/./b -es/$/---/\;q; cat; } <in >out

...will not only replace only the first empty line w/ three hypens, it will also instruct sed to quit trying to read the input file as soon as the first empty line is found and simply cat the rest. If you are using GNU sed you'll want to use the -unbufferred switch, though.

  • Why don't you let sed do it alone?
    – cuonglm
    Sep 11, 2015 at 2:50
  • @cuonglm - because then it would continue to line-buffer input and scan every line against a regex. cat just copies I/o.
    – mikeserv
    Sep 11, 2015 at 8:41
  • Hmm, really. I think my loop -e:1 -en\;b1 just copy i/o, too. Where did regex scan come from?
    – cuonglm
    Sep 11, 2015 at 8:44
  • 1
    @cuonglm - no. At the least it is still breaking input into \newline delimited sections, and so it is still performing at least that simple scan on input. cat requests a read() from the kernel and immediately copies all that is returned to a write(). The sed loop has to scan the read() bit and divide it on newlines before write() ing each section out (though most sed's buffer output by default, so it just splits it up and pastes it back together again).
    – mikeserv
    Sep 11, 2015 at 8:49
  • 1
    @cuonglm - depending on your sed, though, you can get similar behavior with r\ /dev/stdin.
    – mikeserv
    Sep 11, 2015 at 8:55


sed 's/^$/---/' Chapter1Rev4.md

to do this in all empty lines. For doing it in the first, I would use awk like this:

cat Chapter1Rev4.md | awk '{ if ($0 == "") { n++; if (n<2) print "---"; else print $0 } else print $0}'

(or redirect output to new file with appended > newfile).

  • 2
    With GNU sed you can write sed '0,/^$/{s/^$/---&/}' file to replace only the first empty line.
    – user000001
    Sep 10, 2015 at 18:34
  • 2
    +1 or even just sed '0,/^$/ s//---/' file Sep 10, 2015 at 18:35
  • Thanks you two, I use sed a lot but never needed that.
    – Ned64
    Sep 10, 2015 at 18:41

Another sed:

sed -e '/^$/{
}' -e:1 -en\;b1 <file
  • 1
    Unfortunately this seems to miss the first empty line when it is outputted.
    – Jonathan
    Sep 11, 2015 at 20:25
  • @JonAndrew: Maybe your empty line is not empty. It can contain invisible character like tabs, sapces.
    – cuonglm
    Sep 12, 2015 at 1:47

with a it would look like this:

sed '0,/^$/{
/^$/a \
}' yourfilename

or, if you want to substitute instead of append:

sed '0,/^$/{s/^$/---/}' yourfilename

the sed scripts — for clarity

# from the first line through the first empty line
  # no \ needed here, just append it
  /^$/a ---


# from the first line through the first empty line
   # replace empty lines with `---'

this works because the block's addresses limit it to a certain range (the first line throught the first empty newline), only at the line where the block closes will it's only command, s/^$/---/, get to do anything.

  • I get this when I run the second command, appending the line: 'bad flag in substitute command: '}''. On the first, for substituting, I get this: 'unexpected EOF (pending }'s)'.
    – Jonathan
    Sep 11, 2015 at 20:22
  • the second command being sed '0,/^$/{s/^$/---/}' yourfilename? Sep 11, 2015 at 20:27
  • just found what you were talking about. It should be all good now! Sep 11, 2015 at 20:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.