A Linux textbook covering sed command gives me an example as follow:

sed -e 's/\(<[^ ]*>\)\([ ]*\)\(<[^ ]*>\)/\3\2\1/g'
GNU Linux is cool
Linux GNU cool is 

but while I typing exactly the same command as the about one, it shows me:

sed -e 's/\(<[^ ]*>\)\([ ]*\)\(<[^ ]*>\)/\3\2\1/g'
GNU Linux is cool
GNU Linux is cool

Anyone can help me solve this? I'm using Ubuntu 12.04LTS. Many thanks.

  • 1
    You forgot to tell us the input source for sed. – Radu Rădeanu Mar 15 '14 at 10:17
  • @RaduRădeanu Just echo "GNU Linux is cool" | sed ... - They're doing it interactivly above but echo/pipe is quicker for testing. – Oli Mar 15 '14 at 10:20
  • If an answer solves your issue please take a minute and check the check mark under the vote count to the left, this will signify to everyone that your issue's been resolved. – terdon Mar 15 '14 at 19:39

It may just be a problem with the forum formatting, but the < and > are presumably intended to be word anchors and as such need backslash escapes \< and \>

sed -e 's/\(\<[^ ]*\>\)\([ ]*\)\(\<[^ ]*\>\)/\3\2\1/g'


echo 'GNU Linux is cool'| sed -e 's/\(\<[^ ]*\>\)\([ ]*\)\(\<[^ ]*\>\)/\3\2\1/g'
Linux GNU cool is

However like the previous posters I'd also suggest using the GNU -r extended form to cut down the number of escapes

sed -re 's/(\<[^ ]*\>)([ ]*)(\<[^ ]*\>)/\3\2\1/g'

The word anchors would not seem to be necessary at all if you change the * (zero or more) to + (one or more)

echo 'GNU Linux is cool'| sed -re 's/([^ ]+)([ ]+)([^ ]+)/\3\2\1/g'
Linux GNU cool is
  • thanks steeldriver, it solves my problem. BTW, any other case I should use backslash escapes? – jswxy1 Mar 15 '14 at 14:52
  • @terdon sorry, i forgot. – jswxy1 Mar 19 '14 at 13:28

Well I don't know. There were a few problems here:

  • You need extended mode on for these matches (-r)
  • You don't need script mode on (-e) but that wasn't an error
  • There was a lot of bracket escaping which was syntatically incorrect ( you needed those to match)
  • I couldn't work out what the angle brackets were for at all. So I nuked them.
  • /g global mode breaks it because it swaps the last three words and breaks the space. Try it if you like.

And here it is working:

$ echo "GNU Linux is cool" | sed -r "s/([^ ]*)([ ]*)([^ ]*)/\3\2\1/"
Linux GNU is cool

A better/shorter/easier-to-read way to do this would be to nuke the second group and just use a literal space. Like so:

$ echo "GNU Linux is cool" | sed -r "s/([^ ]*) ([^ ]*)/\2 \1/"
Linux GNU is cool

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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