Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to nest sed substitutions?

Tags:

regex

sed

I want to change the format of every line in a file, and also run another substitution on one of the matched groups.

As an example, I could have a simple three-column CSV file (without escapes) that I wanted to put in another format.

sed -r 's/^([a-z]+),([a-z]+),([a-z]+)$/\1: \3 (\2)'
# would turn "comma,separated,values"
# into       "comma: values (separated)"

However, I also want to remove all the vowels from the second column, i.e. run s/[aeiou]//g on \2.

Is there a nice solution to this problem of nesting substitutions? Please assume that both substitutions are complicated, and that this was just an example.

My sed is not GNU sed version 4.0.

like image 656
Tim Avatar asked Nov 04 '22 18:11

Tim


2 Answers

I think you're better off with awk for this one, to make it easier to manipulate the fields.

echo "gaviidae,gruidae,picidae" | awk -F "," '{gsub(/[aeiou]/, "", $2); printf("%s: %s (%s)\n", $1, $3, $2)}'

outputs:

gaviidae: picidae (grd)
like image 135
Simon Avatar answered Nov 09 '22 11:11

Simon


This is cryptic (like almost any non-trivial sed) but it'll do the job. It takes advantage of the fact that you want the modified word to go at the end-- the same trick will work if you want it to go to some other position, but the command will be a little longer.

sed 'h;s/.*,([a-z]+),.*/(\1)/;s/[aeiou]//g;x;s/([a-z]+),[a-z]+,([a-z]+)/\1: \2 /;G;s/\n//'

Or in English: "save a copy in the hold buffer, kill all but the second word, strip out the vowels, swap the buffers, rearrange the words (dropping the middle one), add the other buffer onto the end, remove the new-line".

like image 42
Beta Avatar answered Nov 09 '22 12:11

Beta