Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations TouchToneTommy on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Changeable modifiers in a regex

Status
Not open for further replies.

markasmith

Programmer
May 12, 2008
3
GB
Hi,

Using Perl 5.6.1, I need a reg-ex which is sometimes case-sensitive, sometimes case-insensitive, according to something which happened earlier.

I've tried this:
$caseSensitiveCharacter = "i";
(or) $caseSensitiveCharacter = "";
[...then...]
if ( /^somestuff$/$caseSensitiveCharacter )
(or) if ( /^somestuff$/\Q$caseSensitiveCharacter\E )
but neither works:
Scalar found where operator expected
(or) Backslash found where operator expected

Any suggestions? You can have bits of the body of the reg-ex in variables using /Q and /E - but I need the modifier to be in a variable.

Many thanks!
 
What is the deciding factor for which version you must use?
There is probably a way to do it all in one but I would use a sub routine for each version to get the job done quickly.

Keith
 
Well it boils down to there being a variable which (by some earlier magic) is now '1' if we are to be case-insensitive, or 0 if case-sensitive.

Are the values of $1, $2 etc. available to you as the top level if set by a reg-ex from within a subroutine?

I've thought of a way of doing it...

if ( ((1==$caseInsens) && ($a =~ /blah/i ) )
|| ((0==$caseInsens) && ($a =~ /blah/ ) ) )
{
...
}

...which looks a bit messy, but does work. Would be really nice if I could have that 'i' in a variable, though...

Thanks for the reply!
-Mark
 
I only suggested subs in case the regex and associated code were more complex. For your use, a simple statement would suffice.
Code:
if($caseInsens == 1){
$a =~ /blah/i;
}else{
$a =~ /blah/;
}

Keith
 
:) They are quite complex... the code within the if{} more than the regex itself. Unfortunately I can't do it exactly as you suggest because I need "if $a =~ /blah/ {loads of stuff which is all common to the two checks, and which I don't want to duplicate}", not just "$a =~ /blah/".

The nagging issue with my version is that it relies on order of evaluation to work. (I use the resulting $1 and $2 in my code - so it's essential it doesn't try to evaluate the 'wrong' regex or it may trash over them.) Of course you CAN rely on order of evaluation, it's not left to chance, but it still makes me uneasy.

Cheers,
Mark
 
You can set a variable to a regex pattern complete with its flags using the qr operator
Code:
use strict;
use warnings;

my $case_sensitive = shift || 0;

my $string = "Steve";
my $match = "steve";

my $rx = $case_sensitive == 1 ? qr/$match/ : qr/$match/i;

print "Matched\n" if ($string =~ $rx);
So if you run this with a parameter of 1, it doesn't match. Anything else, the match is case insensitive, so it matches. I'm not sure that this is necessarily cleaner, prettier, or better than your own example, but at least it's using the operator that was designed for the purpose...[smile]

Steve

[small]"Every program can be reduced by one instruction, and every program has at least one bug. Therefore, any program can be reduced to one instruction which doesn't work." (Object::perlDesignPatterns)[/small]
 
Steve
I thought there would be a way to do it.
The only problem I see with that is 6 months down the line, when you return to the script, remembering what that clever bit of code actually does.
Add some comments now!



Keith
 
You can embed (?i) into the regexp itself if you want to turn on case-insensitive matching, something like:
Code:
my $regexp = '^somestuff';

$regexp = "(?i)$regexp" if ( $case_insensitive );
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top