Issue
I have a string with 3 capture groups and would like to preserve the first and third but perform a substitution on the second. How do I express this in sed?
Concretely, I have an input string like:
top-level.subpath.one.subpath.two.subpath.forty-five
And I want to preserve the part before the first .
, shorten the middle part to the first letter of every word, and preserve the part after the last .
. The result should look like:
top-level.s.o.s.t.s.forty-five
For preserving the capture groups, I have:
sed -r 's/([^.]*)(.*)(\..*)/\1...\3/'
which gets me:
top-level....forty-five
For converting something like .subpath.one.subpath.two.subpath
to only initials, I have:
sed -r 's/(\.[^.])[^\.]*/\1/g'
which gets me:
.s.o.s.t.s
I'd like to essentially apply that second sed expression to capture group 2. Is there some way I can chain sed substitutions to perform that second substitution on only the second capture group while retaining the first and third?
Solution
A simple awk
solution that will work with any version of awk including MacOS:
s='top-level.subpath.one.subpath.two.subpath.forty-five'
awk 'BEGIN{FS=OFS="."} {for(i=2;i<NF;++i) $i=substr($i,1,1)}1' <<< "$s"
top-level.s.o.s.t.s.forty-five
This awk
command uses .
as input and output field separator. We loop through field position 2
to last-1
and replace value of each field with the first character of that field. In the end we print full record.
A BSD sed
solution to do the same:
sed -E -e ':x' -e 's/(.+\..)[^.]+\./\1./; tx' <<< "$s"
top-level.s.o.s.t.s.forty-five
Answered By - anubhava Answer Checked By - Mary Flores (WPSolving Volunteer)