How do I use a new-line replacement in a BSD sed?
Asked Answered
S

4

22

Greetings, how do I perform the following in BSD sed?

sed 's/ /\n/g'

From the man-page it states that \n will be treated literally within a replacement string, how do I avoid this behavior? Is there an alternate?

I'm using Mac OS Snow Leopard, I may install fink to get GNU sed.

Stoical answered 14/9, 2009 at 13:13 Comment(1)
Small correction: \n isn't treated literally as such, it gets translated to literal n (i.e., the `` is dropped; but that obviously still isn't the desired outcome).Consummation
E
24

In a shell, you can do:

    sed 's/ /\
/g'

hitting the enter key after the backslash to insert a newline.

Elysian answered 14/9, 2009 at 13:18 Comment(2)
Fantastic, thanks Wooble. Is there any known reason why BSD sed doesn't support \n in the replacement string? Just curious.Stoical
I'm not sure, but it seems they just decided to not support escapes at all in the replacement string. sed 'y/ /\n/' seems to work, although it only does string replacement; if you need to replace the ' ' with a regex it will fail. Also, the \n seems to be special-cased; \r with get you an 'r', not a carriage return.Elysian
C
10

Another way:

sed -e 's/ /\'$'\n/g'

See here.

Carbolated answered 9/11, 2013 at 22:9 Comment(1)
+1, but note that this relies on a shell feature, ANSI C quoting ($'...'), and some shells do not support it (e.g., dash - it's not part of POSIX). Also,'s/ /\'$'\n''/g' - wedging a $'\n' between two single-quoted strings - is conceptually clearer and more robust. Alternatively, use $'s/ /\\\n/g' (note the need to escape the \ ).Consummation
O
7

For ease of use, i personally often use

cr="\n" 
# or (depending version and OS)
cr="
"

sed "s/ /\\${cr}/g"

so it stays on 1 line.

Optional answered 11/11, 2013 at 6:58 Comment(4)
Interesting; can I suggest calling the variable nl rather than cr? Assuming you use a shell that supports ANSI C quoting (e.g., bash, ksh, zsh), you could simplify the assignment to cr=$'\n'; then you wouldn't have to worry about platform differences.Consummation
cool advice, sur about the $'\n' on any "unix" ? it will indeed help (my Sun give me some issue on assignation/action like that with \n)Optional
$'\n' (ANSI-C quoting) should work if you have the right shell (bash, ksh, or zsh - NOT in POSIX-features-only shells such as dash, however), so the platform should not matter. (bash introduced the feature in version 2.0 (a loooong time ago) - not sure about ksh, and zsh, but I would expect current systems to have recent-enough versions).Consummation
In NetBSD 9.3, this gives me the error unterminated substitute in regular expression :-( I genuinely cannot find a way to make sed use newlines in NetBSD, but you could use awk -v RS=" " "{print}" instead, taken from this answerWoothen
U
0

To expand on @sikmir's answer: In Bash, which is the default shell on Mac OS X, all you need to do is place a $ character in front of the quoted string containing the escape sequence that you want to get interpreted. Bash will automatically translate it for you.

For example, I removed all MS-DOS carriage returns from all the source files in lib/ and include/ by writing:

grep -lr $'\r' lib include | xargs sed -i -e $'s/\r//'
find . -name '*-e' -delete

BSD grep would have interpreted '\r' correctly on its own, but using $'\r' doesn't hurt.

BSD sed would have misinterpreted 's/\r//' on its own, but by using $'s/\r//', I avoided that trap.

Notice that we can put $ in front of the entire string, and it will take care of all the escape sequences in the whole string.

$ echo $'hello\b\\world'
hell\world
Ungulate answered 5/4, 2018 at 21:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.