Today I had to face the fact that the
sed
in Darwin 9.4.0 (Mac OS X Leopard 10.5.4) lacks a lot of functionality.
Eg. you cannot embed backslash-escaped characters in the replacement expression of an
s
function.
The following will output "abcnef" and not "abc" + newline + "ef":
echo 'abcdef' | sed 's/d/\n/'
Backslash-escaped sequences are not recognized in bracket expressions either. So you cannot match a tab character with
[\t]
or a newline with
[\n]
.
![Sad Sad](/sites/all/modules/smiley/packs/Roving/aw.png)
This is "normal" behaviour, at least for the Darwin
sed
, but quite unfortunate and makes life a lot more difficult. Eg. there's no way around this regexp (that should match a single line with the newline preceding it) without support for backslash-escapes in brackets:
\n[^\n]*
You can use the
[:cntrl:]
character class as a substitute, but of course it's just a workaround and functionally not equivalent:
\n[^[:cntrl:]]*
However there're problems even with documented functionality. Eg. this
sed
does not support extended regular expressions as described in the
re_format
manpage. But the
sed
manpage says that extended regexps are described there.
Eg. the following will output an error instead of "Xc" (the regexp is taken from the
re_format
manpage):
echo 'chchcc' | sed -Ee 's/[[.ch.]]*c/X/'
So multi-character sequences are not accepted as a collating element and you'll get an error message like
"RE error: invalid collating element".
Another weirdness: Darwin's
sed
is quite sensitive about separating functions/commands with newlines. You'll find that in many cases you simply must put in a newline here and there or your code won't be accepted. Eg. if you create a function-list, the terminating
}
must be preceded by a newline, a semi-colon won't do it. Also labels are likely to cause you headaches if you don't put them into their own line. In GNU sed you can create nice (gigantic
![Smile Smile](/sites/all/modules/smiley/packs/Roving/smile.png)
) one-liners, because a semi-colon can replace a newline virtually everywhere in the script.
PS: most probably the problems with the Mac OS X
sed
are not specific to Darwin, but came from the FreeBSD roots. Maybe FreeBSD's
sed
worked always like this.
![Smile Smile](/sites/all/modules/smiley/packs/Roving/smile.png)
Maybe it's the GNU sed that is "out of the line".
![Smile Smile](/sites/all/modules/smiley/packs/Roving/smile.png)
Imho the way GNU sed interprets backslashed escape sequences makes it a lot more "user friendly".
Comments
I agree - damn Apple
Try: echo 'abcdef' | sed
echo 'abcdef' | sed $'s/d/\\\n/'
See also:
Multi-line pattern matching with sed
http://codesnippets.joyent.com/posts/show/2111
Re: Try: echo 'abcdef' | sed
sed
in Mac OS X still does not interpret backslashed escape sequences.(Btw. meanwhile I've upgraded to Snow Leopard and
sed
is still crippled ... at least compared to the GNU sed.)Mac OS X uses FreeBSD sed,
http://rudix.org/packages.html
And there even is minised that recognizes backslash-escaped characters as well:
http://freshmeat.net/projects/minised
echo 'abcdef' | minised 's/d/\n/'
(minised needs to be compiled from source though)
cheers
Re: Mac OS X uses FreeBSD sed
fink install sed
. I wrote the post to call attention to the differences between thesed
in Mac OS X (ie. FreeBSD) and the GNU sed and how a lot of things are "broken" in the former. It's not that I couldn't have installed GNU sed on my Mac anytime. I'm just a bit annoyed by the fact that the builtin sed is missing so many features that GNU sed users got used to.