Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Perl > Perl Misc > regular expression like AND match

Reply
Thread Tools

regular expression like AND match

 
 
ikeon
Guest
Posts: n/a
 
      12-23-2008
The case is that I need to search for a couple of strings in a line. I
don't know the order that they will be matched and I need them all to
be matched.
like if (string1|string2|string3) can find one of the strings (OR) , I
need it to match all of the strings (like AND) and again - I don't
know the order that they will appear.
I know how to do it if I will check the line 3 times in some loop, but
I need to know if it can be done in one regular expression.

Thanks,
 
Reply With Quote
 
 
 
 
Peter Makholm
Guest
Posts: n/a
 
      12-23-2008
ikeon <(E-Mail Removed)> writes:

> I know how to do it if I will check the line 3 times in some loop, but
> I need to know if it can be done in one regular expression.


Yes, it can be done in a single regular expression, but why do you
need to do it in a single regular expression?

It's quite easy by using the correct look-around assertion, but I
guess it will be neither faster nor more maintainable than doing
something like:

/pat1/ && /pat2/ && /pat3/


//Makholm
 
Reply With Quote
 
 
 
 
Mirco Wahab
Guest
Posts: n/a
 
      12-23-2008
ikeon wrote:
> The case is that I need to search for a couple of strings in a line. I
> don't know the order that they will be matched and I need them all to
> be matched.
> like if (string1|string2|string3) can find one of the strings (OR) , I
> need it to match all of the strings (like AND) and again - I don't
> know the order that they will appear.
> I know how to do it if I will check the line 3 times in some loop, but
> I need to know if it can be done in one regular expression.


This is nontrivial (imho) but can be done using
code assertions. The magic lies in setting a signal
denotig a specified hit during the match, e.g.
setting a bit in a word for each string matched.

Example:

...

# what to find
my @strings = qw'string1 string2 string3';

# where to find
my @lines = ('first line string1 ',
'second line string1 string2 ',
'third line string1 string2 string3 ');
#expect: only line #3 shall match

# make regex out of the search strings above (note the 'bts' thing)
my $cnt = 0;
my $reg = join '|', map $_.'(?{$bts|='.(1<<$cnt++).'})', @strings;

# apply regex to the lines
foreach my $line (@lines) {

our $bts = 0; # used within the regex engine
use re 'eval';
# ignore line unless the 'bits' 1,2,3 are in place
next unless () = $line=~/$reg/g, $bts == 7;

# we got one, do something ($bts was 7)
print "$line\n"

}

...

Regards

M.
 
Reply With Quote
 
Jürgen Exner
Guest
Posts: n/a
 
      12-23-2008
ikeon <(E-Mail Removed)> wrote:
>The case is that I need to search for a couple of strings in a line. I
>don't know the order that they will be matched and I need them all to
>be matched.
>like if (string1|string2|string3) can find one of the strings (OR) , I
>need it to match all of the strings (like AND) and again - I don't
>know the order that they will appear.
>I know how to do it if I will check the line 3 times in some loop, but
>I need to know if it can be done in one regular expression.


Is there anything wrong with something like

if (/string1/ or /string2/ or /string3/) {
...
}

resp.
if (/string1/ and /string2/ and /string3/) {
...
}

jue
 
Reply With Quote
 
Jim Gibson
Guest
Posts: n/a
 
      12-23-2008
In article
<(E-Mail Removed)>,
ikeon <(E-Mail Removed)> wrote:

> The case is that I need to search for a couple of strings in a line. I
> don't know the order that they will be matched and I need them all to
> be matched.
> like if (string1|string2|string3) can find one of the strings (OR) , I
> need it to match all of the strings (like AND) and again - I don't
> know the order that they will appear.
> I know how to do it if I will check the line 3 times in some loop, but
> I need to know if it can be done in one regular expression.


In scalar context, 'grep {BLOCK} LIST' will return the number of times
BLOCK evaluates to true for the members of LIST. So you can put your
strings to be found in an array and do something like:

my @strings = qw( string1 string2 string3 );
my $string = '... string3 ... string1 ... string2 ...';
my $n = grep { $string =~ /$_/ } @strings;
if( $n == @strings ) {
print "All strings found\n";
}

This method has the advantage over the

if( /string1/ && /string2/ && /string3/ ) { ... }

method in that you can vary the number of strings to be matched without
changing the matching code.

--
Jim Gibson
 
Reply With Quote
 
Peter Makholm
Guest
Posts: n/a
 
      12-24-2008
Mirco Wahab <(E-Mail Removed)> writes:

> my $reg = join '|', map $_.'(?{$bts|='.(1<<$cnt++).'})', @strings;


Wow. Simple look ahead assertions would du just fine. Don't turn it
into rocket science just because the single regexp requirement is
silly.

//Makholm
 
Reply With Quote
 
sln@netherlands.com
Guest
Posts: n/a
 
      12-24-2008
On Tue, 23 Dec 2008 06:16:55 -0800 (PST), ikeon <(E-Mail Removed)> wrote:

>The case is that I need to search for a couple of strings in a line. I
>don't know the order that they will be matched and I need them all to
>be matched.
>like if (string1|string2|string3) can find one of the strings (OR) , I
>need it to match all of the strings (like AND) and again - I don't
>know the order that they will appear.
>I know how to do it if I will check the line 3 times in some loop, but
>I need to know if it can be done in one regular expression.
>
>Thanks,


Alot of good suggestions already.
I guess you could do something like this as well.

sln

---------------------------------------------------
use strict;
use warnings;


my @strings = ("find this", "that too", "and other");
my $patrx = join '|', @strings;
$patrx = qr/$patrx/;

my $fpos = tell(DATA);

## To match all or some -
while (<DATA>)
{
chomp; next if (!length);
my %seen = ();

if (s/($patrx)/$seen{$1}=$1/eg && (keys %seen) == @strings)
{
# matched all
my $found = join ',', keys %seen;
print "found ALL: '$found'\n\tin '$_'\n";
}
else
{
# matched some or none
my $found = join ',', keys %seen;
print "found ".(keys %seen)."/".@strings.": '$found'\n\t in '$_'\n";
}
}

print "====================\n";
seek(DATA, $fpos, 0);

## To match any -
while (<DATA>)
{
chomp; next if (!length);

if (/($patrx)/)
{
# matched one
print "found '$1'\n\t in '$_'\n";
}
}


__DATA__

first line string1
second line string1 string2 find this
third line string1 string2 string3
find this", "that too", "and other


 
Reply With Quote
 
 
 
Reply

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 On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
regular expression match and exclude Azalar --- Ruby 6 09-08-2008 03:04 PM
Regular Expression - looking to match 'www' only if it the start of a URL hooterbite@yahoo.com ASP .Net 4 07-12-2005 01:01 PM
how to match regular expression from right to left Liang Perl 2 08-27-2004 10:03 PM
match three digit number using regular expression championsleeper Perl 6 04-06-2004 08:54 PM
Dynamically changing the regular expression of Regular Expression validator VSK ASP .Net 2 08-24-2003 02:47 PM



Advertisments