Take the 2-minute tour ×
Ask Ubuntu is a question and answer site for Ubuntu users and developers. It's 100% free, no registration required.

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.

share|improve this question
1  
You forgot to tell us the input source for sed. –  Radu Rădeanu Mar 15 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 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 at 19:39

2 Answers 2

up vote 3 down vote accepted

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'

i.e.

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
share|improve this answer
    
thanks steeldriver, it solves my problem. BTW, any other case I should use backslash escapes? –  jswxy1 Mar 15 at 14:52
    
@terdon sorry, i forgot. –  jswxy1 Mar 19 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
share|improve this answer
    
Thanks Oli~ It helps~ –  jswxy1 Mar 15 at 14:54

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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