I'm working on learning how to use regular expressions, and have found a conversion that has me stuck.

Given the statements:

1. pi=3.14 and pie
2. pie and pi=3.14

How do I match pi and turn it in to 3.14 without also catching pie? This is user input, so I can't rely on position in the string.

My attempt was:
s/pi\W/3.14/g

That almost worked, but the \W ate the equals sign so I got:
3.143.14 and pie

Thanks in advance for any help. (This is not homework, but it is school related.)

Use this replace block: s|((?<![\w\d])pi(?![\w\d]))|3.14|g It has a negative lookbehind (?<![\w\d]) and lookahead (?![\w\d]) for characters preceeding and following the word pi. For more about lookahead/behinds:

http://www.perl.com/pub/a/2003/07/01/regexps.html


Proofs:

my ($in) = "8 * pie";
$in =~ s/((?<![\w\d])pi(?![\w\d]))/3.14/g;
#result: $in = 8 * pie
my ($in) = "epi * 7";
$in =~ s/((?<![\w\d])pi(?![\w\d]))/3.14/g;
#result: $in = epi * 7
my ($in) = "pi * 4";
$in =~ s/((?<![\w\d])pi(?![\w\d]))/3.14/g;
#result: $in = 3.14 * 4
my ($in) = "pi * 4 * epi + pi / pie";
$in =~ s/((?<![\w\d])pi(?![\w\d]))/3.14/g;
#result: $in = 3.14 * 4 * epi + 3.14 / pie

PS: You may want to do another replace for multiplication shorthand: on paper 3PI * 4 is valid math markup; but if your passing this through an eval block; 3[pi replaced] isn't going to be the same. The block I've given you will NOT replace instances like this: 3PI. but it would replace the PI in instances like this: 3 PI (the space between 3 and PI is the key here). On that capitilized note, you may want to replace the "pi" in the block with (pi|PI|pI|Pi) a-la: $in =~ s/((?<![\w\d])(pi|PI|pI|Pi)(?![\w\d]))/3.14/g; or do:

$in = lc($in); #convert characters to lowercase
$in =~ s/((?<![\w\d])pi(?![\w\d]))/3.14/g;

parsing user input for all possible syntax variations is an excersize in frustration as Matts code above shows. If you want to simply find "pi=3.14" a turn it into 3.14:

s/pi=3\.14/3.14/g;

or if 'pie=3.14' is a possibility too:

s/pie?=3\.14/3.14/g;

and last, if case sensitive matching is not wanted:

s/pie?=3\.14/3.14/ig;

Thanks for the help! I'll take apart the regexp and figure out what each part does. :-)

Implicit multiplication gets hard when you stop limiting variable names to one letter... but it's the better way to do it!

This article has been dead for over six months. Start a new discussion instead.