Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

sed multiple repacement in a line

Tags:

regex

sed

It may be a very basic question but I am not able to form the sed on liner for this.

Consider this line

foo@some_text/48183 bar@another-test/22787 xyz@some_another_text/2291

I want to replace everything from "@" to space separated by comma. So my expected output should look like

foo,bar,xyz

I was trying sed -e 's/@.*[^ ]/,/g' to replace till space however it is replacing whole whole line(not so good in writing regular exp).

Any help will be appreciated.

like image 442
g_p Avatar asked Jan 03 '23 07:01

g_p


2 Answers

You may find and capture any 1+ chars other than @ before a @ char, then match @ and any 0+ chars other than whitespace followed with 0+ whitespace chars, and replace all that with a placeholder to Group 1 and a comma. Then, you will have to remove the trailing comma.

See a sed demo:

s='foo@some_text/48183 bar@another-test/22787 xyz@some_another_text/2291'
echo "$s" | sed -E 's/([^@]+)@[^[:space:]]*[[:space:]]*/\1,/g' | sed 's/,$//'

Note that you may also use sed 's/\([^@][^@]*\)@[^[:space:]]*[[:space:]]*/\1,/g' insead of the POSIX ERE version. In BRE POSIX, you should escape ( and ) to form a capturing group, and + quantifier should be escaped, or replaced with a aa* construction.

Details

  • ([^@]+) - Capturing group 1: 1+ chars other than @
  • @ - a @ char
  • [^[:space:]]* - 0+ chars other than whitespace
  • [[:space:]]* - 0+ whitespace chars

The \1 is a placeholder for the text captured with the capturing group #1.

The second sed 's/,$//' is used to remove the trailing , at the end of the string.

like image 91
Wiktor Stribiżew Avatar answered Jan 14 '23 05:01

Wiktor Stribiżew


The basic problem with the match part of your regex (@.*[^ ]) is that .* matches almost the whole rest of the source string after the first @ (a quite common error) and [^ ] matches the last non-space char.

If you use @\S+\s* as the match part, then \S+ matches "non-space" part (e.g. some_text/48183) and \s* matches optional spaces thereafter.

This replacement gives foo,bar,xyz,, so you should somehow delete the last comma.

like image 34
Valdi_Bo Avatar answered Jan 14 '23 05:01

Valdi_Bo