I was trying to write a sed command where if it finds a colon without surrounding spaces, it will put one space before and after the colon, that is, abc:def will be converted to abc : def. I am doing like this:

echo "abc:def" | sed -e 's/[^\s]\+:[^\s]\+/ : /g'

the output is still abc:def, how do I do it? what is wrong with my above command?

2 Answers 2


\s to mean space in sed is not portable - for example in POSIX implementations your expression will not match e.g. (GNU sed, in posix mode):

$ echo "abc:def" | sed --posix -e 's/[^\s]\+:[^\s]\+/ : /g'

However if your expression did match, it would not do what you want since it will replace the entire sequence e.g. (GNU sed, in non-posix mode):

$ echo "abc:def" | sed -e 's/[^\s]\+:[^\s]\+/ : /g'

Probably what you want is something more like s/\([^[:blank:]]\):\([^[:blank:]]\)/\1 : \2/ e.g.

$ echo "abc:def" | sed -e 's/\([^[:blank:]]\):\([^[:blank:]]\)/\1 : \2/g'
abc : def

[As far as I can see the repetition operator \+ - which is also not portable - is unnecessary.]



echo "abc:def" | sed 's@\([^\s]\):\([^\s]\)@\1 : \2@g'

I've tested this with GNU sed, not sure about BSD sed.

You need capture groups if you want to preserve parts of the original match, which is what the \(...\) and \1 and \2 are doing. Also, you don't need the + qualifier since all you care about is the immediate neighbors.

  • sed on OpenBSD seems to work with your expression.
    – Kusalananda
    Aug 31, 2017 at 12:17

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .