tandrewnichols
tandrewnichols

Reputation: 3466

How do I correctly use captured groups from sed in my replacement text?

Just not enough of a sed user to be able to figure this out. I'm trying to convert from underscore to lodash, which requires changing many invocations from _(obj).method() to _.method(obj). I've been trying to do this with sed using this:

sed "s/_(\(.*\)).\(.*\)(/_.\2(\1, /"

This pattern actually works fine for a single instance in a line. E.g.

echo "_(foo).bar('blah')" | sed "s/_(\(.*\)).\(.*\)(/_.\2(\1, /"

actually outputs the expected result: _.bar(foo, 'blah'). The problem is when there are multiple occurrences on a single line. E.g.

echo "_(foo).bar('baz') yep _(baz).quux('blah')" | sed "s/_(\(.*\)).\(.*\)(/_.\2(\1, /"

outputs _.quux(foo).bar('baz') yep _(baz, 'blah') and

echo "_(foo).bar('baz') yep _(baz).quux('blah')" | sed "s/_(\([^(]*\)).\(.*\)(/_.\2(\1, /"

outputs _.bar('baz') yep _(baz).quux(foo, 'blah').

So, I obviously just don't understand exactly how to use capture groups in my replacement texts. And incidentally, adding /g to the end does not resolve this.

Upvotes: 1

Views: 53

Answers (1)

Kent
Kent

Reputation: 195229

is this what you are looking for?

sed -r 's/_\(([^)]*)\)\.([^(]*\()([^)]*\))/_.\2\1,\3/g'

with your example:

kent$  echo "_(foo).bar('baz') yep _(baz).quux('blah')" | sed -r 's/_\(([^)]*)\)\.([^(]*\()([^)]*\))/_.\2\1,\3/g'
_.bar(foo,'baz') yep _.quux(baz,'blah')

update, comments on your codes:

I took a look on your codes, and did some modification, now it works here.

Yours : sed "s/_(\([^(]*\)).\(.*\)(/_.\2(\1, /"
Mine  : sed "s/_(\([^)]*\))\.\([^(]*\)(/_.\2(\1, /g"
  • keep in mind, sed does always greedy match, so, you have to use [^something]. check the places I changed.
  • dot (.) should be escaped when you want it to match literal ..
  • g flag is needed

Upvotes: 2

Related Questions