On Saturday 22 May 2010, Jim Gibson wrote:
> On 5/21/10 Fri May 21, 2010 12:13 PM, "Akhthar Parvez K"
> <[email protected]> scribbled:
> > Shouldn't
> > Perl be smart enough to understand that the outer most pair of paranthesis
> > and
> > | symbol were solely used for alternation (since there're nothing within the
> > outermost paranthesis except another set of paranthesis and alternation) and
> > it doesn't need to pick something out of it.
>
> In general, Perl (nor any other language) will try to figure out what you
> want and give you just that. Other people will want different things. You
> need to tell Perl exactly what you want using Perl syntax. For regular
> expressions, this means returning a value for each set of () in your regex.
>
> If you don't want the outer set of parentheses to capture, then use
> non-capturing parentheses: (?: ). See 'perldoc perlre' and search for
> "Extended Patterns".
Jim, thanks for your continued help.
Jim, forget everything that I "scribbled" upto now, how would you tell Perl to
pick 'cd' of 'abcd' and 'abcd' itself and 'pq' of 'pqrs' and 'pqrs' itself, and
nothing else, from an array ( = 'abcdpqrsxyz') by a single statement.
my @data = 'abcdpqrsxyz';
my %matches = <your statement>;
foreach my $cut (keys %matches)
{ print "$cut => $matches{$cut}\n"; }
and the output should be:
abcd => cd
pqrs => pq
Your answer would be much appreciated.
The example code mentioned in my previous posts was just a demonstration of the
issue I'm facing. Actual regex pattern and data are very much different. And
the regex is the only option to get the desired output here, but even that's
not giving me the *exact* output I want.
> > I've earlier been using a for loop to get both the matched part and
> > the critical part. However, I thought it would be better if I can avoid the
> > loop as that would cause an unwanted delay if there are more strings to be
> > matched, so I thought to get it done in a single statement, or a group of
> > statements, without any loop.
>
> Perl loops are very fast and will not introduce any noticeable delays in
> your program. Regular expressions can be slow in some applications,
> particularly if they contain lots of wild-cards and you are using them on
> long strings. In either case, you are not likely to notice a difference. If
> you are noticing a delay, then there is some other explanation than the use
> of a for loop. If you do not have a delay problem but are just looking for
> more speed, then you need to benchmark your program to see where it is
> spending the most time.
>
> Note that a while loop is more appropriate than a for loop for iterating
> over the matches in a regex with the /g modifier. Something link (untested):
>
> while( m{ (?: a+(b+) | c+(d+) )}xg ) {
> if( $1 ) {
> # a+(b+) was matched, $1 contains b+
> }else{
> # c+(d+) was matched, $2 contains d+
> }
> }
>
I don't think the example code mentioned by you is gonna help me in this case.
I've previously been using a different method. I did a for loop with regex
patterns and searched through the data contents for each pattern. So if the
data size is a bit higher, it would take more time when there're many regex
patterns. That's why I thought of concatenating the regex using alternation and
get this done without a loop.
--------------------------
Earlier it was: version1
foreach my $regx (@regex)
{if (my @matches = map { /($regx)/ } @data)
{ print "$matches[0] => $matches[1]\n";
}
}
matches[0] would contain the matched string and $matches[1] would contain the
critical string. However, the problem with that was, it would search through
the data for n number of times where n is the total number regex patterns. If
the @data is big enough, this would be waste of time.
Output: fine (just as I wanted)
abcd => cd
pqrs => pq
--------------------------
So I modified them to: version2
my @matches2 = map { /($regx)/g } @data;
foreach (@matches2)
{if ($_) # throw away the undefs
{foreach my $regx (@regex)
{if (my @matches = /($regx)/)
{ print "$matches[0] => $matches[1]\n"; }
}
}
}
so that the matched part of the data (@data) is stored into another array
(@matches2 - size of this array would be a lot smaller, offcourse) and the
patterns are matched with this filtered data in the loop, hence this method
would be a lot better.
Output: fine (just as I wanted)
abcd => cd
pqrs => pq
--------------------------
This won't take much time, but I thought it would be more elegant if I could
avoid the regex loop, hence I tried the code mentioned in my previous post.
version3:
my $regx = join ("|", @regex);
my %matches = map { /($regx)/g } @data;
foreach my $cut (keys %matches)
{ print "$cut => $matches{$cut}\n"; }
output: not as I wanted:
Use of uninitialized value in list assignment at ./regex22.pl line 11.
Use of uninitialized value in list assignment at ./regex22.pl line 11.
=> pq
abcd => cd
keys of %matches would contain the matched part ($1) and their values will be
the critical part for the particular string ($2). It looked great for a moment,
but then I noticed the undefs returned by map function caused the issue here.
If I can't get rid of those undefs, I'll have to go back to the version2 code.
--
Regards,
Akhthar Parvez K
http://tips.sysadminguide.com/
UNIX is basically a simple operating system, but you have to be a genius to
understand the simplicity - Dennis Ritchie
--
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]
http://learn.perl.org/