Peter O'Brien Peter O'Brien - 4 months ago 6x
Perl Question

Search and replace unix command line, perl capture group empty

I'm trying to perform a recursive search and replace of file content.

Given the below in a number of files:

something: 'ha',
somethingElse: 'ah'

I'd like to end up with:

something: 'ha',
somethingElse: 'ah',
somethingNew: 'ah ha'

On Mac OS X, I am trying the following from command line from within a parent directory:

find . -type f -exec perl -p -i -e "s/somethingElse:(.*)/somethingElse:$1,\n\tsomethingNew: 'ah ha'/g" {} \;

It's almost working except the capture group is interpreted as blank resulting in:

something: 'ha',
somethingNew: 'ah ha'

What's the problem?

Also not tied to
, I don't mind an alternative approach (can use
for example)


Thanks to @123 for answer in the comments:

You need to use single quotes. The $1 is interpreted by bash before perl, therefore it is empty when perl sees it. Or just escape it, as you use single quotes in your replacement.

Thus translating to:

find . -type f -exec perl -p -i -e 's/somethingElse:(.*)/somethingElse:$1,\n\tsomethingNew: '\''ah ha'\''/g' {} \;


find . -type f -exec perl -p -i -e "s/somethingElse:(.*)/somethingElse:\$1,\n\tsomethingNew: 'ah ha'/g" {} \;

It might also be wise to add a file extension when doing this, one guess why: you may perform accidentally from too high a directory and corrupt say version control files, i.e.

find . -type f -name '*.json' -exec perl -p -i -e "s/somethingElse:(.*)/somethingElse:\$1,\n\tsomethingNew: 'ah ha'/g" {} \;

The originally accepted answer which was deleted suggested \1 rather than $1. Whilst this worked it was noted as bad practice by other commenters.