Reputation: 5506
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.
Upvotes: 4
Views: 58
Reputation: 12456
You can also do it the other way around even if it might be a bit more pipy
.
$ echo "foo@some_text/48183 bar@another-test/22787 xyz@some_another_text/2291" | (tr ' ' ',' | grep -oP '(?=,|^)[^@]+' | tr -d '\n'; echo "")
foo,bar,xyz
Instead of replacing, part of the string you can directly extract the relevant parts.
Explanations:
tr ' ' ','
in order to replace all spaces by commas. grep -oP '(?=,|^)[^@]+'
to fetch everything before the @
. It uses perl regex with lookaround (imposing the constraint that the preceding character is either a comma or the beginning of the string and accept all the characters except @
.tr -d '\n'
is used to remove the EOL inserted by grep
echo ""
may be omitted if you do not need to have an ending \n
. You can then simplify the command in tr ' ' ',' | grep -oP '(?=,|^)[^@]+' | tr -d '\n'
Upvotes: 2
Reputation: 133760
Following awk
may help you here.
awk 'BEGIN{OFS=","}{for(i=1;i<=NF;i++){sub(/@.*/,"",$i)}} 1' Input_file
Solution 2nd: Taking code from Wiktor Stribizew's post and modifying it a bit to convert it to a single sed
now.
sed -E 's/([^@]+)@[^[:space:]]*[[:space:]]*/\1,/g;s/,$//' Input_file
Upvotes: 2
Reputation: 31011
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.
Upvotes: 2
Reputation: 627469
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 charsThe \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.
Upvotes: 3