tags:

views:

105

answers:

5

Hi, I am still a beginner with Perl, so please bear with me. This is the situation I'm experiencing:

$var = "AB1234567";
$num = "1234567";
next if $var =~ /$num/;
print "Success!\n";

Now, my understanding is that it should print "Success!\n", but in reality it doesn't. However, if I change the regex to next if $var =~ /"$num"/;, this will actually print "Success!\n".

However, if I change it to $var = "AB123456";, the original regex will work fine.

I understand that when enclosing strings using double quotations, it will dereference interpolate the variable. However, should it not be true in the case of regex? I've done regex using variables without quotations and it worked fine.

Thanks for your help!

EDIT:

I left out semi-colons in my example, but my original problem still stands.

EDIT:

I really should've just copied/pasted. I made a typo and used continue if instead of next if. Again, my problem still exists.

+4  A: 

I don't think so. This works for me:

$var = "AB1234567";
$num = "1234567";
print "Success!\n" if $var =~ /$num/;

It is either something with your continue statement or the fact that you are missing semicolons in the variable assignments (your example doesn't even run for me....).

alpha123
Oops, I forgot about those semi-colons. I have edited my original post to include them now. Thanks.
Evan
+4  A: 

I think you are confused on what continue does. I'm not really sure of what you are trying to do here, but generally continue will break out of an if-block or go to the next iteration of a for-loop, while-loop, etc. When the pattern does match, continue is actually skipping over the print statement. When you change the value of $var, it no longer matches and the print statement is reached.

Try this:

$var = "AB1234567"
$num = "1234567"
print "Success!\n" if $var =~ /$num/;

Randy

rjray
Good catch. I think I meant to use "next if" instead. I'll try your example right now.
Evan
Hmm...no, your example still didnt work for me. Thanks though.
Evan
Actually, your example did work for me. It didn't work at first because I left the "next if" statement before it. Thanks, although I'm still curious why my original code doesn't work.
Evan
@Evan See my answer to understand why your original code does not work. Then, read `perldoc perlsyn` also available at http://perldoc.perl.org/perlsyn.html.
Sinan Ünür
+1  A: 

http://perldoc.perl.org/functions/index.html

C:>perl -e "$x='abc'; $y='bc'; print 'yes' if index($x,$y)>0;"
yes
C:>perl -e "$x='abc'; $y='bc'; print 'yes' if $x =~ /$y/"
yes

If (as is implied) the code is in a loop, you might be interested in qr{} in http://perldoc.perl.org/perlop.html#Regexp-Quote-Like-Operators

RedGrittyBrick
Well, my original example wasn't in a loop, and I'm betting you saw my original code where I used "continue if". I meant to use "next if". Thanks for your reply though =) The link you provided me gave me a better understanding of regex.
Evan
A: 

Your code says "If this variable matches this regular expression, do nothing. Otherwise, print Success!.". I doubt that's what you meant for it to do.

Adding the quotation marks does not affect whether the variable is interpolated at all. What it does do is cause the regular expression match to fail. Since the match fails, the next[1] is not executing and execution reaches the print statement and Success! is printed.

The problem with your code is not at all related to regular expressions or to variable interpolation into regular expressions or to quotation marks appearing inside regular expressions. It is a simple logic error of an inverted conditional.

Try replacing the third line with

next unless $var =~ /$num/;

to see what happens when you simply invert the logic of your code to what you probably intended.

[1]: or continue, depending on which version of your code one is looking at

darch
+4  A: 

Let's look at your code:

$var = "AB1234567";
$num = "1234567";
next if $var =~ /$num/;
print "Success!\n";

I am assuming this is in the body of some loop. When you say

next if $var =~ /$num/;

You are saying "go back and execute the loop body for the next iteration, skipping any following statements in the look body if $var matches /$num/". When $var does indeed match /$num/, the program does exactly what you asked for and skips the print statement.

On the other hand, when you use $var =~ /"$num"/, the pattern on the right hand side becomes /"1234567"/. Now, the conditional in next if $var =~ /"$num"/ cannot succeed. And, your program prints "Success" because the match failed.

#!/usr/bin/perl

use strict; use warnings;
use re 'debug';

my $num = "1234567";

for my $var ( qw( AB1234567 ) ) {
    next if $var =~ /$num/;
    print "Success!\n";
}

Output:

Compiling REx "1234567"
Final program:
   1: EXACT  (4)
   4: END (0)
anchored "1234567" at 0 (checking anchored isall) minlen 7
Guessing start of match in sv for REx "1234567" against "AB1234567"
Found anchored substr "1234567" at offset 2...
Starting position does not contradict /^/m...
Guessed: match at offset 2
Freeing REx: "1234567"

Now, let's use /"$num"/ as the pattern:

#!/usr/bin/perl

use strict; use warnings;
use re 'debug';

my $num = "1234567";

for my $var ( qw( AB1234567 ) ) {
    next if $var =~ /"$num"/;
    print "Success!\n";
}

Output:

Compiling REx "%"1234567%""
Final program:
   1: EXACT  (5)
   5: END (0)
anchored "%"1234567%"" at 0 (checking anchored isall) minlen 9
Guessing start of match in sv for REx "%"1234567%"" against "AB1234567"
Did not find anchored substr "%"1234567%""...
Match rejected by optimizer
Success!
Freeing REx: "%"1234567%""

Your code prints Success! when the match fails.

See also perldoc perlsyn:

The next command starts the next iteration of the loop:

    LINE: while (<STDIN>) {
    next LINE if /^#/;  # discard comments
    ...
    }
Sinan Ünür