http://www.perlmonks.org?node_id=23240


in reply to Search and Replace

My test string was:
$s = "Bla (bar;) bla bla; bla bla (foo; bar); bla bla Bla bla bla; bla bla (foo; bar); bla bla Bla bla bla; bla bla (foo; bar); bla bla Bla bla (bar;foo;bar) bla; bla bla (foo; bar); bla bla Bla bla bla; bla bla (foo; bar); bla bla ";

(It probably isn't a good idea to "embed" newlines in that way, but doing so worked ok for test purposes just now.)

The regular expression I used was similar to what Ovid suggests:

$s =~ s/\(([^)]*);([^)]*)\)/($1,$2)/g;

The difference was in the placement of the parens. I decided to store "$1" and "$2" inside the literal parens and then re-insert the literal parens so that they'd kind of jump out at me--what's happening in the substitution would be slightly more obvious to me if I had to look at it some time later. Maybe. :)

The regular expression breaks down as shown below. Note that in the following I've added the modifier "x", which doesn't appear above. "x" should be used if you want to break the regular expression onto several lines and add comments, as it's done here:

s/ # search for... \( # a literal "(" ( # begin storing what follows (in "$1") [^)]* # zero or more of anything that is *NOT* ")" ) # stop storing in "$1" ; # a semicolon ( # begin storing what follows (in "$2") [^)]* # zero or more of anything that is *NOT* ")" ) # stop storing in "$2" \) # a literal ")" /($1,$2)/gx; # and replace all that with...see below...

... replace it with a literal "(", followed by whatever was stored in "$1", followed by a comma, followed by whatever was stored in "$2", followed by a literal ")".

Modifier: "g" = everywhere within the string (see above concerning "x").

This regular expression worked with strings such as (foo;bar) and (;bar) and (foo;), but it did not work for a string such as (foo;bar;boink).

Note that if you were to use one of the proposed solutions containing<kbd> .*</kbd>: if your input file contains newlines, and if you're doing these replacements after "slurping" the entire file at once into a variable, for safety's sake add the "s" modifier to the substitution. (See perlre for more about the modifiers.

Taking my lead from the mavens here: remember to "use strict;" and to check your syntax with "-w"...