I want to find a x, and replace the 0 or more following spaces (\s*) with just a single space.

echo "x ax" | sed 's/x\s*/x /'

For some reason, instead of replacing the spaces with the single space, it just appends one space to however many existed there before:

x  ax

The use of + instead of * appears to absolutely nothing, regardless of my use of the -E flag.

It appears that sed doesn't do non-greedy expressions, so why doesn't this * consume all of the spaces when matching?

I'm a regex ninja in non-bash settings, but bash and its tools eat me alive. I've got no idea how to concisely phrase this for a successful search engine query.


sed expects a basic regular expression (BRE). \s is not a standard special construct in a BRE (nor in an ERE, for that matter), this is an extension of some languages, in particular Perl (which many others imitate). In sed, depending on the implementation, \s either stands for the literal string \s or for the literal character s.

In your implementation, it appears that \s matches s, so \s* matches 0 or more s, and x\s* matches x in your sample input, hence x ax is transformed to x ax (and xy would be transformed to x y and so on). In other implementations (e.g. with GNU sed), \s matches \s, so \s* matches a backslash followed by 0 or more s, which doesn't occur in your input so the line is unchanged.

This has absolutely nothing to do with greediness. Greediness doesn't influence whether a string matches a regex, only what portion of the string is captured by a match.

| improve this answer | |
  • I believe you are the most correct. I tried apparently every combination of character class that I could think of, but using a literal space makes this regex work with the version of sed I'm using. What boggles my mind, however, is the use of the valid flag -E on this system to enable ERE, I also cannot successfully use [:space:], which my man re_format says is acceptable. Nothing but a literal ` ` works here. – Tim Feb 6 '13 at 0:34
  • 2
    @Tim What sed implementation are you using? Did you write x[[:space:]] and not x[:space:]? – Gilles 'SO- stop being evil' Feb 6 '13 at 0:45

I think you are getting your sed and grep flags mixed up. -E is the grep flag for extended regular expressions. -r is the sed flag for extended regular expressions. The following works for me:

echo "x     ax" | sed -r 's/x\s*/x /'

It produces

x ax
| improve this answer | |
  • Hum. I'm realizing belatedly that BSD sed manpages are looking pretty different right about now. -r isn't a valid flag on this system. I need to regroup and figure out what's up. – Tim Feb 6 '13 at 0:15
  • @Tim Stephen is refering to the flags of GNU grep. – Gilles 'SO- stop being evil' Feb 6 '13 at 0:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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