2

How would someone use sed to go about reordering groups of substrings within a string separated by commas?

For instance,

hello bob, my name is, joseph

becomes:

joseph, My name is, hello bob

2 Answers 2

3

With this as the test file:

$ cat file
hello bob, my name is, joseph

We can reorder the fields as you like with:

$ sed -E 's/([^,]*), *([^,]*), *([^,]*)/\3, \2, \1/' file
joseph, my name is, hello bob

How it works

A sed substitute command has the form s/old/new/. This replaces old with new where old is a regex. In this case, old is:

([^,]*), *([^,]*), *([^,]*)

The items in parens are groups. This separates the line into three comma-separated groups. We can refer to these three groups as \1, \2, and \3 respectively. In the new text, then, we use:

\3, \2, \1

This reverses the order of the groups, putting the third first and the first last, as you requested.

Handling an indefinite number of columns

If we want to reverse all the substrings but the number of substrings is unknown in advance, then awk is a good tool to use:

$ awk -F', *' '{for (i=NF;i>0;i--)printf "%s%s",$i,(i>1?", ":"\n")}' file
joseph, my name is, hello bob

-F', *' indicates that we want to use a comma optionally followed spaces as the field delimiter.

for (i=NF;i>0;i--)printf "%s%s",$i,(i>1?", ":"\n") loops in reverse over each field and prints it followed either by , or, for the last one, a newline.

Reversing words within substrings

Here is an example of reversing words within a substring:

$ sed -E 's/([^ ,]*) ([^,]*), /\2 \1, /' file
bob hello, my name is, joseph

Here is an example of reversing the words within a substring while also reversing substring order:

$ sed -E 's/([^ ,]*) ([^,]*), *([^,]*), *([^,]*)/\4, \3, \2 \1/' file
joseph, my name is, bob hello
Sign up to request clarification or add additional context in comments.

4 Comments

What if there is an indefinite amount of groups?
@KennyLau In that case, I would use awk. See updated answer for the awk code.
Thanks! What if I wanted to use sed to then reorder words within the same group as well?
@user OK. I added some examples of that as well.
0

You can also use awk :

awk -F', ' '{ print $3 ", " $2 ", " $1 }' <<< "hello bob, my name is, joseph"
#joseph, my name is, hello bob

Update:
Based on @andlrc's comment, this solution is simpler:

awk 'BEGIN{FS=OFS=", "}{print $3, $2, $1}' <<< "hello bob, my name is, joseph"

2 Comments

You can use awk 'BEGIN{FS=OFS=", "}{print $3, $2, $1}', this way you don't need to hardcode , 3 times
Always learning... I'll update my answer with your comment, tks !

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.