Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses

Perl & Regex

by Kzin (Acolyte)
on Sep 08, 2004 at 22:33 UTC ( #389503=perlquestion: print w/replies, xml ) Need Help??

Kzin has asked for the wisdom of the Perl Monks concerning the following question:

Hey there all you Perl Monks, I am new to the fold so please go easy on me ;-) My question is with regards to perl and regex... I seem to get different results with the line...
if( /Price: \$([0-9]+\.[0-9]+)/ )
$searchString = 'Price: \$([0-9]+\.[0-9]+)'; ... if ( /$searchString/ )
What is it doing?
Well it is supposed to parse my website for changes, so that if anyone does change I am notified. It seems to work fine when the actual regex is in the if itself, but it wont match when I have it assigned to the variable.
So what is my question?
Is this normal behavior? Should the fact that the regex string is contained in a variable change the final outcome of what matches and what doesn't?
P.S the content of a grabbed webpage is assigned to $_ before the if happens.

Replies are listed 'Best First'.
Re: Perl & Regex
by borisz (Canon) on Sep 08, 2004 at 22:55 UTC
    What difference do you see?
    Both regex looks the same to me.
Re: Perl & Regex
by Velaki (Chaplain) on Sep 08, 2004 at 22:49 UTC

    Seems to work for me. I ran the following code, and I get the result of match. Is there anything else in your code?

    #!/usr/bin/perl use strict; use warnings; my $searchstring = 'Price: \$([0-9]+\.[0-9]+)'; $_ = 'This is a test. Price: $1.30'; if( /$searchstring/ ) { print "match\n"; } __END__ match

    By the way, you can also set up the regex using the qr operator, like:

    my $searchString = qr/Price: \$([0-9]+\.[0-9]+)/;

    Wish I could help more,
    "Perl. There is no substitute."
Re: Perl & Regex
by osunderdog (Deacon) on Sep 08, 2004 at 22:54 UTC
    If you would like to use a regex as a variable, you should use qr. For example:
    use strict; my $string = 'Price: $21343.355344'; my $searchString = qr|^Price: \$([0-9]+\.[0-9]+)|; if($string =~ /$searchString/) { print "Matches: $1\n"; } else { print "No Match: $`\n"; }
    I think you are getting messed up because $( gets replaced with $REAL_GROUP_ID (ie $( ...)
      Thanks I will try qr =) Will post again if I have a problem still. Sounds like this could solve the problem I am having.
      > If you would like to use a regex as a variable, you should use qr.

      Not always. There are some advantages to using qr. There are some disadvantages as well. 1) qr takes more memory than a string, which may matter if you have a lot of them. 2) in some cases, if you construct a large regex out of many small parts, qr is significantly slower than using strings - this is because in non-trivial interpolations, a qr-ed regex first gets stringified, which gives lots of extra parenthesis.

      #!perl -w use Devel::Size 'size'; print size('Price: \$([0-9]+\.[0-9]+)'), "\n"; print size(qr/Price: \$([0-9]+\.[0-9]+)/), "\n"; __END__ 50 104
      edited out
      Allright, that didn't quite seem to do the trick...
      Ok here is the code, however I have changed the company to one *similar* to my own, just for example purposes. I dont claim affiliation to these guys disclaimer stuff goes here.
      #!/usr/bin/perl use LWP::UserAgent; use Net::SMTP; $ua = LWP::UserAgent->new; my ($req, $match, $res, $name, $url, $price, $readPath, $write +Path, $companyName, $ccemail); my $changes=""; my $searchString=""; my $searchString2=""; $email = ''; # $tag represents a <blah> tag in html $tag = "<[^>]*>"; $readPath = "/home/autotasks/pricemonitor/"; $companyName = "LensMart"; $searchString = qr|^Price: \$([0-9]+\.[0-9]+)|; $searchString2 = qr|^Price: $tag\$([0-9]+\.[0-9]+)|; open( CONTACTS, "<$readPath$companyName" ) ; # list being read open( CONTACTS2, ">$readPath.$companyName"); # new list being +generated while( <CONTACTS> ) { chomp($_); ($name, $url, $price) = split(/###/, $_); $savename = $name; $name =~ s/\(/\\(/g; $name =~ s/\)/\\)/g; $req = HTTP::Request->new(GET => $url); $res = $ua->request($req); $_ = $res->content; # the "if" statement below looks for the product name +and price if( /$searchString/ ) { $match = $1; # check if price is the same if( $1 == $price ) {} else { # price changed, so add to "changes" l +ist $changes .= "$savename($url) - changed + from \$$price to \$$1 \n\n"; } print CONTACTS2 "$savename###$url###$1\n"; } elsif ( $searchString2 ne "" ) { if( /$searchString2/ ) { $match = $1; # check if price is the same if( $1 ne $price ) { # price changed, so add to "ch +anges" list $changes .= "$savename($url) - + changed from \$$price to \$$1 \n\n"; } print CONTACTS2 "$savename###$url###$1 +\n"; }else { print CONTACTS2 "$savename###$url###$p +rice\n"; $changes .= "No match on $savename($ur +l)\n\n"; } }else { print CONTACTS2 "$savename###$url###$price\n"; $changes .= "No match on $savename($url)\n\n"; } } close( CONTACTS ); close( CONTACTS2); # copy new list onto old one to ensure things are the same nex +t time system( "cp $readPath.$companyName $readPath$companyName" ); # if prices changed, email if( $changes ne "" ) { system ("date"); print "$companyName:\n$changes"; $smtp = Net::SMTP->new('localhost'); # connect to an S +MTP server $smtp->mail( $email ); if ($ccemail ne "") { $smtp->to($email, $ccemail); }else { $smtp->to($email); } $smtp->data(); # Send the header. $smtp->datasend("To: $email \n"); $smtp->datasend("From: $email\n"); $smtp->datasend("Subject: $companyName Price Changes\n +"); $smtp->datasend("\n"); # Send the body. # $smtp->datasend("$changes\n"); $smtp->dataend(); $smtp->quit; }else { system("date"); print "$companyName: No change\n"; } # End Of File
      I apologise ahead of time for lack of good meaningful comments and have to give credit to various sources from around the 'net for little tips here and there... like the qr thing. So the 'net owns this not me. hehe
      The file that it is reading from would be named "LensMart" or whatever you put in for company name. An example line would be...
      Acuvue### dId=1/cur=1/cam=LM602###15.95
      You could put many lines in that file, but I dont really want to go through that person's site and pull up all of their individual products. Dont forget to change the readpath to wherever you are going to put the file. This works best with linux because I have prepended the second file with . to hide it, as it is really just a temp file. I dont know what windows will do in this situation.
      Ok thats enough babbling, I shall now leave it to those who are more wise.
        Was wondering if anyone was able to get this code to work?

        By Kzin
Re: Updated: Perl & Regex
by Anonymous Monk on Sep 09, 2004 at 10:03 UTC
    # cat r /Price: \$([0-9]+\.[0-9]+)/; $searchString = 'Price: \$([0-9]+\.[0-9]+)'; /$searchString/; # perl -Dr r 2>&1 | grep Compiling Compiling REx `Price: \$([0-9]+\.[0-9]+)' Compiling REx `Price: \$([0-9]+\.[0-9]+)' #
      Yikes! Like I said, go easy on me! (hehe)

      What I get from this is that you are demonstrating that there is absolutley no difference between assigning to a variable and searching for the string alone. Please do correct me if I am wrong, I am but a lowly initiate. (Translated: recv(MONASTERY,$enlightenment,$daily,0); credit to saint MZSanford's Monk Levels)

      Did you try to run the source I posted? The reason I came in search of the Monk's wisdom is because it seems completley illogical as to why it would work one way and not the other.

      If you run the code and recieve "No match on Whateveritemitisthatifound (http://urlforthatitem)" then it wasn't able to match.
      If you get "No Change" or "Changed from XX.XX to XX.XX" then the regex was working fine.
      I know I could just put these strings right into the if, but I was hoping to make this script more dynamic, and eventually just have my separate websites as header files that are parsed and automatically run by one central program... But baby steps, baby steps.

      Ok, thats enough rambling from me for now, thank you all for your help to current, and I cant wait to hear more suggestions. (Even if it is "this code worked fine on my machine!")

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://389503]
Approved by Velaki
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others exploiting the Monastery: (2)
As of 2022-05-18 05:55 GMT
Find Nodes?
    Voting Booth?
    Do you prefer to work remotely?

    Results (68 votes). Check out past polls.