LinuxQuestions.org
Register a domain and help support LQ
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Reply
 
LinkBack Search this Thread
Old 11-04-2009, 12:19 PM   #1
kdelover
Member
 
Registered: Aug 2009
Posts: 297

Rep: Reputation: 36
pattern matching help in perl


hello ppl,

Is it possible to match a numeric pattern in using regex in perl? I want to print something if the variable my $a has a numeric value between 000 and 999? How do i do that,i cant seem to find a solution for that.

my $a=;
{
if ($a=~<in range 000-999> {
print "In range";
else {
print "Not in Allowed Range";
}

Thanks.
 
Old 11-04-2009, 12:51 PM   #2
Telemachos
Member
 
Registered: May 2007
Distribution: Debian
Posts: 754

Rep: Reputation: 59
You can use Perl's grep function to test if something is included in a list, and the range is a kind of list. This is an indirect test, but it works. (In a nutshell, if the item isn't found in the list, grep will return false. So it can function as a pseudo-boolean here.)

So, something like this works, I believe:
Code:
#!/usr/bin/env perl
use strict;
use warnings;

print "Gimme a value: ";
chomp(my $a = <STDIN>);

if (grep { $a == $_ } (000..999)) {
    print "In Range\n";
}
else {
    print "Out of range\n";
}
Even smarter, however, is to use the first function from List::Util because grep will run through all the numbers no matter what, but first will bail out the moment it gets a hit. (E.g., if the included number is 001, grep keeps going, but first stops right away.)
Code:
#!/usr/bin/env perl
use strict;
use warnings;
use List::Util qw/first/;

print "Gimme a value: ";
chomp(my $a = <STDIN>);

if (first { $a == $_ } (000..999)) {
    print "In Range\n";
}
else {
    print "Out of range\n";
}

Last edited by Telemachos; 11-04-2009 at 01:06 PM.
 
Old 11-04-2009, 03:12 PM   #3
kdelover
Member
 
Registered: Aug 2009
Posts: 297

Original Poster
Rep: Reputation: 36
Thanks telemachos,its working,but it doenst work when i write something like this

if (grep(/(000..999)/,$a))

Program gets executed for every value i input it says out of range.
 
Old 11-04-2009, 04:48 PM   #4
Telemachos
Member
 
Registered: May 2007
Distribution: Debian
Posts: 754

Rep: Reputation: 59
Quote:
Originally Posted by kdelover View Post
Thanks telemachos,its working,but it doenst work when i write something like this

if (grep(/(000..999)/,$a))

Program gets executed for every value i input it says out of range.
Right, that doesn't work. It looks like you're trying to use a simpler syntax of grep where it does a default regular expression test, but a regular expression match won't work here.

Here's how grep works:
  • You give grep a block and a list. (There's also an alternative form where you use an expression and a list - which is what it looks like you were trying to do - but I think that the block form is better in general and better suited for this task. So I'm only going to talk about that form here. See perldoc -f grep for the full story.)
  • Perl takes goes through the items in the list, one at a time, setting $_ to each member of the list in turn.
  • Inside the block, you write some kind of test. It can be a regular expression match, but it can also be something else.
  • If the test comes out true for an item, that item is passed along by grep. If not, the item is not passed along.
  • In list context, grep returns the list of items that passed the test. In scalar context, grep returns the number of items that passed the test. (A good thing to keep in mind if you want to check how many items in a given array or hash match a certain criterion.)

I used grep in a conditional - a scalar context. In essence, grep will return 1 (if the number is in range) or 0 (if the number is not in range). 1 evaluates in Perl to true, so the if code is executed. 0 evaluates as false, so the else code is run.

But the way the test block works is that I test whether each item (aliased to $_ by Perl automatically) is equivalent to one of the items in the range. When grep finds a match, it returns 1. The test itself is not a regular expression, but a simple numeric equality test:
Code:
grep { $a == $_ } (000..999)
This checks is $a numerically equal to 001, 002, 003, 004 etc. I think this is the test you want, rather than a regular expression.
 
Old 11-05-2009, 01:56 PM   #5
kdelover
Member
 
Registered: Aug 2009
Posts: 297

Original Poster
Rep: Reputation: 36
Thanks telemachos for the explanation :-), I used the grep function in my code and it works,but i am not sure if this is an efficient way of doing it. All i have to do is take input from user,and the input has to be of this standard ABC-XXX,Where ABC- will be a default entry for any put only the XXX (Which is an interger from 000 to 999) must vary,For Ex: ABC-001,ABC-100...etc

Code:
print "Enter ID number";
chomp ($Id=<STDIN>);             
if ($Id) {
my @Arr = split('-',$Id)
if(($Arr[0] eq "ABC") and (grep{$Arr[1] == $_}(000..999)) {
print "ID Number Valid";
}
else {
print "Not Valid";
}
The Bad thing in the above code is am using 2 lines of code,along with split function and comparing the values using grep function,where i guess it can be done using a simpler regex. Thanks again for the help!!
 
Old 11-05-2009, 06:10 PM   #6
Telemachos
Member
 
Registered: May 2007
Distribution: Debian
Posts: 754

Rep: Reputation: 59
Quote:
Originally Posted by kdelover View Post
The Bad thing in the above code is am using 2 lines of code,along with split function and comparing the values using grep function,where i guess it can be done using a simpler regex. Thanks again for the help!!
I hear what you're saying, and I hadn't realized that you count narrow in on a regex quite so much. (I was imagining a more complex situation.) Still, I got curious a wrote a simple benchmark script. The results are worth looking at:
Code:
#!/usr/bin/env perl
use strict;
use warnings;
use List::Util qw/first/;
use Benchmark qw(:all);

my $grep_way = sub {
    my @caught;
    while (<DATA>) {
        my @fields = split('-', $_);
        if (($fields[0] eq 'ABC') and (grep { $fields[1] == $_ }(000..999))) {
            push @caught, $_;
        }
    }
};

my $first_way = sub {
    my @caught;
    while (<DATA>) {
        my @fields = split('-', $_);
        if (($fields[0] eq 'ABC') and (first { $fields[1] == $_ }(000..999))) {
            push @caught, $_;
        }
    }
};

my $regex_way = sub {
    my @caught;
    while (<DATA>) {
        if ($_ =~ m/^ABC-[0-9]{3}$/) {
            push @caught, $_;
        }
    }
};

cmpthese(-15, {
    'Grep:' => $grep_way,
    'Regexp:' => $regex_way,
    'First:' => $first_way,
});

__DATA__
ABC-010
BCC-999
ABC-1011
ABC-001
XCB-111
ABC-010
BCC-999
ABC-1011
ABC-001
XCB-111
ABC-010
BCC-999
ABC-1011
ABC-001
XCB-111
ABC-010
BCC-999
ABC-1011
ABC-001
XCB-111
ABC-010
BCC-999
ABC-1011
ABC-001
XCB-111
Output:
Code:
telemachus ~ $ perl bencher
            Rate  First:   Grep: Regexp:
First:  245782/s      --     -1%     -1%
Grep:   247025/s      1%      --     -1%
Regexp: 248913/s      1%      1%      --
A regular expression here is quicker, but the difference is negligible. Unless you are doing hundreds of thousands of these computations, I would say go with whatever method makes more sense to you. Later, when you have to reread the code (or explain it to someone else), that will matter most.
 
Old 11-07-2009, 01:52 PM   #7
kdelover
Member
 
Registered: Aug 2009
Posts: 297

Original Poster
Rep: Reputation: 36
Thanks you very much telemachos you have been of great help to me with your explanation and examples!! . I wanted to know one more thing,i coudlnt find any chapter regarding connecting to mysql Db in the system admin pdf i downloaded from the site you gave me perltraining.au,is there a seprate tutorial for that which i must download? Thanks again for that site!!
 
Old 11-07-2009, 07:01 PM   #8
Telemachos
Member
 
Registered: May 2007
Distribution: Debian
Posts: 754

Rep: Reputation: 59
Quote:
Originally Posted by kdelover View Post
I wanted to know one more thing,i coudlnt find any chapter regarding connecting to mysql Db in the system admin pdf i downloaded from the site you gave me perltraining.au,is there a seprate tutorial for that which i must download? Thanks again for that site!!
Yup, there's a separate pdf tutorial for database stuff: http://perltraining.com.au/notes/perldbi.pdf
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off
Trackbacks are Off
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
matching pattern in perl vinaytp Linux - Newbie 4 06-21-2009 12:27 PM
need help with perl - pattern matching johngreg Programming 5 10-13-2008 01:08 PM
Perl pattern matching - greedy wondergirl Programming 2 06-17-2008 03:32 PM
Perl pattern matching in VB rigel_kent Programming 1 05-30-2006 11:00 AM
pattern matching in perl ludeKing Programming 9 04-02-2004 09:53 AM


All times are GMT -5. The time now is 09:44 AM.

Main Menu
 
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: @linuxquestions
Open Source Consulting | Domain Registration