LinuxQuestions.org
Go Job Hunting at the LQ Job Marketplace
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
 
Thread Tools
Old 11-04-2009, 01:19 PM   #1
kdelover
Member
 
Registered: Aug 2009
Posts: 159
Thanked: 12
pattern matching help in perl


[Log in to get rid of this advertisement]
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.
linux kdelover is offline     Reply With Quote
Old 11-04-2009, 01:51 PM   #2
Telemachos
Member
 
Registered: May 2007
Distribution: Debian
Posts: 686
Thanked: 47
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 02:06 PM..
macos Telemachos is offline     Reply With Quote


Old 11-04-2009, 04:12 PM   #3
kdelover
Member
 
Registered: Aug 2009
Posts: 159
Thanked: 12

Original Poster
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.
linuxubuntu kdelover is offline     Reply With Quote


Old 11-04-2009, 05:48 PM   #4
Telemachos
Member
 
Registered: May 2007
Distribution: Debian
Posts: 686
Thanked: 47
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.
macos Telemachos is offline     Reply With Quote


Old 11-05-2009, 02:56 PM   #5
kdelover
Member
 
Registered: Aug 2009
Posts: 159
Thanked: 12

Original Poster
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!!
linuxubuntu kdelover is offline     Reply With Quote


Old 11-05-2009, 07:10 PM   #6
Telemachos
Member
 
Registered: May 2007
Distribution: Debian
Posts: 686
Thanked: 47
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.
macos Telemachos is offline     Reply With Quote


Old 11-07-2009, 02:52 PM   #7
kdelover
Member
 
Registered: Aug 2009
Posts: 159
Thanked: 12

Original Poster
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!!
windows_98_nt_2000 kdelover is offline     Reply With Quote


Old 11-07-2009, 08:01 PM   #8
Telemachos
Member
 
Registered: May 2007
Distribution: Debian
Posts: 686
Thanked: 47
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
macos Telemachos is offline     Reply With Quote


Thanked by:

Reply

Bookmarks


Thread Tools

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


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


All times are GMT -5. The time now is 01:32 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
RSS2  LQ Podcast
RSS2  LQ Radio
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: @linuxquestions
Open Source Consulting | Domain Registration