I find that \n doesn't work in sed under Mac OS X. Specifically, say I want to break the words separated by a single space into lines:

# input
foo bar

I use,

echo "foo bar" | sed 's/ /\n/'

But the result is stupid, the \n is not escaped!

foonbar

After I consulted to google, I found a workaround:

echo 'foo bar' | sed -e 's/ /\'$'\n/g'

After reading the article, I still cannot understand what \'$'\n/g' means. Can some one explain it to me, or if there is any other way to do it? Thanks!

You can brew install gnu-sed and replace calls to sed with gsed.

If you don't want to prepend the "g" to sed, you can brew install gnu-sed --with-default-names and just call sed.

(Edit: updated brew flag, hat tip to Clément.)

  • Using the same software on all platform is way easier (at last to me) than dealing with every specificities of the Mac version. Beware, the option is now --with-default-names and not --default-names. However, this option did not worked on my installation, so I had to put a alias gsed=sed in my ~/.profile to make it work. – Clément May 11 '15 at 11:40
  • 4
    This is an ugly workaround. It doesn't explain why sed on OS X behaves the way it does and makes the incorrect assumption that gnu-sed is more correct. Don't be a GNU-addict and stick to POSIX standards to avoid problems in the long run. – octosquidopus Oct 8 '15 at 2:13
  • It is how Apple should make its OS works by default. Why use the name of a program and then make it works differently? I waste an hour because of this... – rascio Apr 4 '17 at 10:58
  • @rascio - because OS X is BSD-like and Linux is Linux-like. – iAdjunct May 30 at 14:30
  • @rascio I think you'll find that GNU sed is the newcomer; BSD sed dates back to 1979 (see en.wikipedia.org/wiki/Version_7_Unix). – Duncan Bayne Sep 10 at 5:19

These would also work:

echo 'foo bar' | sed 's/ /\
/g'

echo 'foo bar' | sed $'s/ /\\\n/g'

lf=$'\n'; echo 'foo bar' | sed "s/ /\\$lf/g"

OS X's sed doesn't interpret \n in the replace pattern, but you can use a literal linefeed preceded by a line continuation character. The shell replaces $'\n' with a literal linefeed before the sed command is run.

  • 4
    Why does sed $'s/ /\\\n/g' work, but not sed $'s/\\\n/ /g'? – Alec Jacobson Jan 3 '16 at 23:03
  • 1
    @alec You can't use sed even in linux/unix to remove newlines because its parsed/split at each newline. If you run this in linux/unix, it won't do anything either: echo -e 'foo\nbar' | sed 's/\n//' – wisbucky Oct 27 '17 at 1:05

The workaround you found passes a single argument string to sed -e.

That argument ends up being a string in the familiar sed s/ / /g format.

That string is created in two parts, one after the other.

The first part is quoted in '...' form.

The second part is quoted in $'...' form.

The 's/ /\' part gets the single-quotes stripped off, but otherwise passes through to sed just as it looks on the command-line. That is, the backslash isn't eaten by bash, it's passed to sed.

The $'\n/g' part gets the dollar sign and the single-quotes stripped off, and the \n gets converted to a newline character.

All together, the argument becomes

s/ /\newline/g

[That was fun. Took a while to unwrap that. +1 for an interesting question.]

The expression $'...' is a bash-ism which produces ... with the standard escape sequences expanded. Th \' before it just means a backslash followed by the end of the quoted section, the resulting string is s/ /\. (Yes, you can switch quoting in the middle of a string; it doesn't end the string.)

POSIX standard sed only accepts \n as part of a search pattern. OS X uses the FreeBSD sed, which is strictly POSIX compliant; GNU, as usual, adds extra stuff and then Linux users all think that is some kind of "standard" (maybe I'd be more impressed if either of them had a standards process).

  • Now I understand the $'...' part. But... what is s/ /\ ? What do you mean by switch quoting? – Ivan Z. G. Xiao Jul 6 '11 at 22:53
  • 2
    '...' is one kind of shell quoting; $'...' is another. There's also "..." and \x to quote a single character. You can combine those in a single word, which is what was being done there, switching from a normal '' string to a $'' string to translate the \n. As for the rest, it's building up a sed command (s/text/replacement/flags). In this case the command is started, including a backslash at the end to protect the literal newline that the $'\n/g' appends. The result is to replace all (the /g flag) spaces with newlines. – geekosaur Jul 6 '11 at 23:01

There's a very easy to visually see what's happening. Simply echo the string!

echo 's/$/\'$'\n/g'

results in

s/$/\
/g

which is equivalent to s/$/\newline/g

If you didn't have the extra \ before the newline, the shell would interpret the newline as the end of the command prematurely.

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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