1

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.

3
  • 1
    You forgot to tell us the input source for sed. Mar 15, 2014 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, 2014 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, 2014 at 19:39

2 Answers 2

3

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
2
  • thanks steeldriver, it solves my problem. BTW, any other case I should use backslash escapes?
    – jswxy1
    Mar 15, 2014 at 14:52
  • @terdon sorry, i forgot.
    – jswxy1
    Mar 19, 2014 at 13:28
1

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
0

You must log in to answer this question.

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