Reputation: 380
there is a string a_b_c_d
. I want to replace _
with -
in the string between a_
and _d
. Below is processing.
echo "a_b_c_d" | sed -E 's/(.+)_(.+)_(.+)/\1`s/_/-/g \2`\3/g'
But it does not work. how can I reuse the \2
to replace its content?
Upvotes: 0
Views: 155
Reputation: 61
Following Kent's suggestion, and if you do not need a general solution, this works:
$ echo 'a_b_c+d_x' | tr '_' '-' | sed -E 's/^([a-z]+)-(.+)-([a-z]+)$/\1_\2_\3/g'
$ a_b-c+d_x
The character classes should be adjusted to match the leading and trailing parts of your input string. Fails, of course, if a or x contain the '-' character.
Upvotes: 0
Reputation: 195179
gnu sed:
$ sed -r 's/_/-/g;s/(^[^-]+)-/\1_/;s/-([^-]+$)/_\1/' <<<'x_a_b_c_y'
x_a-b-c_y
The idea is, replacing all _
by -
, then restoring the ones you want to keep.
if the fields separated by _
contains -
, we can make use ge
of gnu sed:
sed -r 's/(^[^_]+_)(.*)(_[^_]+$)/echo "\1"$(echo "\2"\|sed "s|_|-|g")"\3"/ge'
For example we want ----_f-o-o_b-a-r_----
to be ----_f-o-o-b-a-r_----
:
sed -r 's/(^[^_]+_)(.*)(_[^_]+$)/echo "\1"$(echo "\2"\|sed "s|_|-|g")"\3"/ge' <<<'----_f-o-o_b-a-r_----'
----_f-o-o-b-a-r_----
Upvotes: 1
Reputation: 23677
Perl allows to use code in replacement section with e
modifier
$ echo 'a_b_c_d' | perl -pe 's/a_\K.*(?=_d)/$&=~tr|_|-|r/e'
a_b-c_d
$ echo 'x_a_b_c_y' | perl -pe 's/x_\K.*(?=_y)/$&=~tr|_|-|r/e'
x_a-b-c_y
$&=~tr|_|-|r
here $&
is the matched portion, and tr
is applied on that to replace _
to -
a_\K
this will match a_
but won't be part of matched portion(?=_d)
positive lookahead to match _d
but won't be part of matched portion
With sed
(tested on GNU sed 4.2.2
, not sure of syntax for other versions)
$ echo 'a_b_c_d' | sed -E ':a s/(a_.*)_(.*_d)/\1-\2/; ta'
a_b-c_d
$ echo 'x_a_b_c_y' | sed -E ':a s/(x_.*)_(.*_y)/\1-\2/; ta'
x_a-b-c_y
:a
label a
s/(a_.*)_(.*_d)/\1-\2/
substitute one _
with -
between a_
and _d
ta
go to label a
as long as the substitution succeedsUpvotes: 1