28

Here are my attempts to replace a b character with a newline using sed while running bash

$> echo 'abc' | sed 's/b/\n/'
anc

no, that's not it

$> echo 'abc' | sed 's/b/\\n/'
a\nc

no, that's not it either. The output I want is

a
c

HELP!

Dan Fego
  • 13,644
  • 6
  • 48
  • 59
spraff
  • 32,570
  • 22
  • 121
  • 229
  • 1
    This works for me the way you want it on Ubuntu 11.10 with GNU sed. What version of sed are you using? – Dan Fego Jan 24 '12 at 17:30
  • echo 'abc' | sed 's/b/\n/' works fine on my bash on Debian (Wheezy). My bash version: GNU bash, version 4.1.5(1)-release (x86_64-pc-linux-gnu). My sed version: GNU sed version 4.2.1 – Susam Pal Jan 24 '12 at 17:31
  • Not sure, manpage doesn't say and `sed -V` doesn't work, but I'm on SunOS 5.10 – spraff Jan 24 '12 at 17:33
  • 2
    On Solaris, you can get the POSIX compatible 'sed' by setting this path: PATH=/usr/xpg6/bin:/usr/xpg4/bin:/usr/css/bin:$PATH – Susam Pal Jan 24 '12 at 17:40

5 Answers5

17

Looks like you are on BSD or Solaris. Try this:

[jaypal:~/Temp] echo 'abc' | sed 's/b/\ 
> /'
a
c

Add a black slash and hit enter and complete your sed statement.

spraff
  • 32,570
  • 22
  • 121
  • 229
jaypal singh
  • 74,723
  • 23
  • 102
  • 147
  • Yes! But why do I need the \ before I hit enter? – spraff Jan 24 '12 at 17:34
  • 1
    Once I realized he was on Solaris I tried the manual-`Enter`, but forgot the backslash at the end of the line. Good catch. – Dan Fego Jan 24 '12 at 17:35
  • @spraff Solaris sed is extremely dated, and requires an explicit newline instead of a `\n`. – jaypal singh Jan 24 '12 at 17:36
  • Explicit newline I get, but why the backslash before it? – spraff Jan 24 '12 at 17:37
  • @spraff The backslash is a way of telling `bash` "continue this command on the next line". You can do it with any `bash` command when you want to split it up for clarity. – Dan Fego Jan 24 '12 at 17:37
  • @DanFego Thanks Dan! Trust me I hate working on `solaris` boxes at work after getting used to `GNU` goodies. :) – jaypal singh Jan 24 '12 at 17:38
  • @DanFego Thanks again. Yes @spraff, `backslash` at the end is a way to tell the shell to hold on, there is more stuff coming on the next line. :) – jaypal singh Jan 24 '12 at 17:39
  • @DanFego I use explicit lines in unescaped single quotes in bash at home on Ubuntu and never backslash-prefixed. Which is exceptional, Ubuntu or Solaris? – spraff Jan 24 '12 at 17:39
  • @spraff Solaris is UNIX and Ubuntu is an offshoot of Debian which is Linux. If you add a back slash on your Ubuntu machine it would still work. Since Solaris adheres to POSIX standards if you ever wish to make a script that would work across different platforms adding a backslash will be useful – jaypal singh Jan 24 '12 at 17:42
  • 7
    If you have bash then you should also be able to write it like this, even on Solaris, and have it work: `echo abc | sed 's/b/\'$'\n'/` - the advantage here is that you don't have that pesky significant newline, which makes copying and pasting easier. `$'\n'` is a bashy way to insert literal escape sequences. By the time `sed` sees it it's the same as Jaypal's version. – sorpigal Jan 24 '12 at 17:47
  • 1
    Also: In this case the backslash is NOT being interpreted by bash, but rather by sed. `sed` requires that newlines in the replacement pattern be escaped with \. Consider this: `(set -x ; echo abc | sed "s/b/\$PATH/")` which shows that `bash` has interpreted `\$` and `sed` sees only `$`, vs this: `(set -x ; echo abc | sed 's/b/\'$'\n'/)` which shows that `bash` has expanded `$'\n'` but left the \ before it to `sed`. For comparison try running `echo abc | sed "s/b/\"$'\n'/` and see what you get. – sorpigal Jan 24 '12 at 17:55
  • When I do this on SunOS 5.10 I get the error `sed: command garbled: s/b/\` – pavon Oct 16 '14 at 18:43
  • @sorpigal - please post your upvoted comment as a separate answer, as it's better than most of the others. – user667489 Jul 22 '15 at 19:56
7
$ echo 'abc' | sed 's/b/\'$'\n''/'
a
c

In Bash, $'\n' expands to a single quoted newline character (see "QUOTING" section of man bash). The three strings are concatenated before being passed into sed as an argument. Sed requires that the newline character be escaped, hence the first backslash in the code I pasted.

tboyce12
  • 1,449
  • 14
  • 28
5

You didn't say you want to globally replace all b. If yes, you want tr instead:

$ echo abcbd | tr b $'\n'
a
c
d

Works for me on Solaris 5.8 and bash 2.03

glenn jackman
  • 238,783
  • 38
  • 220
  • 352
1

In a multiline file I had to pipe through tr on both sides of sed, like so:

echo "$FILE_CONTENTS" | \ tr '\n' ¥ | tr ' ' ∑ | mySedFunction $1 | tr ¥ '\n' | tr ∑ ' '

See unix likes to strip out newlines and extra leading spaces and all sorts of things, because I guess that seemed like the thing to do at the time when it was made back in the 1900s. Anyway, this method I show above solves the problem 100%. Wish I would have seen someone post this somewhere because it would have saved me about three hours of my life.

CommaToast
  • 11,370
  • 7
  • 54
  • 69
0
echo 'abc' | sed 's/b/\'\n'/' 

you are missing '' around \n

Ravi Bhatt
  • 3,147
  • 19
  • 21