the output of the replacement is leaving the lines unchanged
This indicates that your regex is not matching the input, so lets take a step back and see if we can get a minimal regex that works:
perl -w -pe "s/INSERT INTO currency (name, code, symbol) VALUES ('(.*?)', '(.*?)', '(.*?)');//" currencies.rb > INSERT INTO currency (name, code, symbol) VALUES ('Baht', 'THB', '?');
Simply removed the replacement and unsurprisingly there is no difference to what you first got, it is not matching the input.
Now the last part of your regex ('(.*?)', '(.*?)', '(.*?)') contains allot of chars that have special meaning in regex so lets remove them and see if that works:
perl -w -pe "s/INSERT INTO currency (name, code, symbol) VALUES .*;//" currencies.rb > INSERT INTO currency (name, code, symbol) VALUES ('Baht', 'THB', '?');
Still not matching, now the only special chars are the () which should probably be escaped:
perl -w -pe "s/INSERT INTO currency \(name, code, symbol\) VALUES .*;//" currencies.rb >
Yup that matches - our input was matched and deleted, so lets add in the end bit again, this time also escaping the other ()s as well:
perl -w -pe "s/INSERT INTO currency \(name, code, symbol\) VALUES \('(.*?)', '(.*?)', '(.*?)'\);//" currencies.rb >
Still matches, so lets add in the replacement again:
perl -w -pe "s/INSERT INTO currency \(name, code, symbol\) VALUES \('(.*?)', '(.*?)', '(.*?)'\);/currency = Currency.find_by_iso(\$&) || Currency.new(:code => '\$&')/" currencies.rb > currency = Currency.find_by_iso(INSERT INTO currency (name, code, symbol) VALUES ('Baht', 'THB', '?');) || Currency.new(:code => 'INSERT INTO currency (name, code, symbol) VALUES ('Baht', 'THB', '?');')
Hmm, seems to be matches the wrong part. This is because & is replaced by the entire matched expression rather than a single subgroup instead you want $1, $2 etc:
perl -w -pe "s/INSERT INTO currency \(name, code, symbol\) VALUES \('(.*?)', '(.*?)', '(.*?)'\);/currency = Currency.find_by_iso(\$2) || Currency.new(:code => '\$2')/" currencies.rb > currency = Currency.find_by_iso(THB) || Currency.new(:code => 'THB')
Almost there, missing some quotes - we also do not require the other two subgroup matches so lets remove them:
perl -w -pe "s/INSERT INTO currency \(name, code, symbol\) VALUES \('.*?', '(.*?)', '.*?'\);/currency = Currency.find_by_iso('\$1') || Currency.new(:code => '\$1')/" currencies.rb > currency = Currency.find_by_iso('THB') || Currency.new(:code => 'THB')
There we go, exactly what we wanted.
When faced with complex regex that does not seem to work it is normally a problem with some of the special chars, it varies from languages to languages and tool to tool - sometimes things need to be escaped sometimes they do not. It always helps to start by stripping out those chars with more simple alternatives until you get a regex that matches part of your input, even if its not exactly the part you want - then expand it back out from there bit by bit until it breaks or you get what you want. If you find the point it breaks you should read up on the documentation for the language/tool you are using to figure out the syntax you are actually looking for.