focus zheng
focus zheng

Reputation: 380

sed Back-references used to replace

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

Answers (3)

user2997577
user2997577

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

Kent
Kent

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.

update

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

Sundeep
Sundeep

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 succeeds

Upvotes: 1

Related Questions