tags:

views:

87

answers:

3

I'm trying to replace text in a source file much like how the C preprocessor works. My approach is to parse constants and their values and populate a hash array with them. My problem is as follows:

In the source file, I have:

#define CONSTANT 10
#define CONSTANT_PLUS_ONE CONSTANT + 1

I use /^#define\s+(\w.*)\s+.*($key).*/ to match the second line, but when I replace with s/$2/$defines{$key}/, both instances of CONSTANT are replaced, i.e.

#define CONSTANT 10
#define 10_PLUS_ONE 10 + 1

I'm something of a Perl novice, so I'm hoping someone can point me in the right direction, or if I've made a blatantly stupid mistake.

+3  A: 

\w.* will match a word character, and then any number of any character, which is not what you want -- you need to bind to word endings, or at least ensure that every character in the match is a word character, e.g. \w+. So try this:

/^#define\s+(\w+)\s+($key).*/

See the full specification of special characters and match types at perldoc perlre.

Ether
This is probably more robust but the problem Conor had was something different, I think.
dreeves
I see what you're saying, Ether. That's a good point. I'll amend this too. Thank you for your advice!
Conor
+5  A: 

Try specifying word boundaries:

s/\b$2\b/$defines{$key}/g;
dreeves
Ah, perfect. I had tried this already and some how messed it up.Thank you dreeves, I think I can sleep now!
Conor
+2  A: 

You can also just run your code through the C preprocessor. Hand it in as STDIN so the compiler doesn't try to get smart and read too much into the file extension.

cc -E - < <file> > <newfile>

And if this is Perl source code you're doing it to, it already has constants. And yes, you get all the performance benefit of inlining.

use constant PI => 3.14;
use constant CAKE => PI + 1.2345;
Schwern