[25967] in Perl-Users-Digest
Perl-Users Digest, Issue: 8186 Volume: 10
daemon@ATHENA.MIT.EDU (Perl-Users Digest)
Sun Jun 19 14:05:25 2005
Date: Sun, 19 Jun 2005 11:05:04 -0700 (PDT)
From: Perl-Users Digest <Perl-Users-Request@ruby.OCE.ORST.EDU>
To: Perl-Users@ruby.OCE.ORST.EDU (Perl-Users Digest)
Perl-Users Digest Sun, 19 Jun 2005 Volume: 10 Number: 8186
Today's topics:
Re: FAQ 6.18 Why does using $&, $`, or $' slow my progr <nobull@mail.com>
Re: Regex with a varrying number of captures <bart.lateur@pandora.be>
Re: Regex with a varrying number of captures <nobull@mail.com>
Digest Administrivia (Last modified: 6 Apr 01) (Perl-Users-Digest Admin)
----------------------------------------------------------------------
Date: Sun, 19 Jun 2005 11:32:58 +0100
From: Brian McCauley <nobull@mail.com>
Subject: Re: FAQ 6.18 Why does using $&, $`, or $' slow my program down?
Message-Id: <d93hkq$45p$1@redhat2.bham.ac.uk>
PerlFAQ Server wrote:
>
> 6.18: Why does using $&, $`, or $' slow my program down?
>
> (contributed by Anno Siegel)
>
> Once Perl sees that you need one of these variables anywhere in the
> program, it provides them on each and every pattern match. That means
> that on every pattern match the entire string will be copied, part of it
> to $`, part to $&, and part to $'. Thus the penalty is most severe with
> long strings and patterns that match often. Avoid $&, $', and $` if you
> can, but if you can't, once you've used them at all, use them at will
> because you've already paid the price. Remember that some algorithms
> really appreciate them. As of the 5.005 release, the $& variable is no
> longer "expensive" the way the other two are.
IMHO this FAQ should also mention that the new special variables @- and
@+ allow you to get most of the beniefits of $` and $' without the cost.
I can't recall when these variables were introduced - I thought it was
after 5.5 but I can't find any mention in perl*delta.
------------------------------
Date: Sun, 19 Jun 2005 11:24:16 GMT
From: Bart Lateur <bart.lateur@pandora.be>
Subject: Re: Regex with a varrying number of captures
Message-Id: <g7lab1hkbdfmoncsqqqdt540i484qis6mm@4ax.com>
Joe Gottman wrote:
>I am parsing a file with several lines of the form
> keyword : value1 value2 ... valueN
>
>What is the easiest way for me to write a regex that will capture all of the
>values? my first pass was
> /^ \s* keyword \s* : (?: \s* (\w+) \b)+/x
>
>but this only captures the last value.
That's indeed an annoying feature (IMO) of Perl regular expressions: you
either capture the lot, or you capture the last value, when you match
with a repeat modifier.
The only solution that I think works reasonably well, is a two step
approach: first match the whole list, and second split up the match into
its parts. For example, like this (though there are other approches, for
example using split):
if(/^ \s* keyword \s* : ((?: \s* \w+ \b)+)/x) {
@parts = $1 =~ /\w+/g;
}
Yes, that is indeed making perl do the same match twice. Double work,
but I know of no one step method.
--
Bart.
------------------------------
Date: Sun, 19 Jun 2005 15:06:13 +0100
From: Brian McCauley <nobull@mail.com>
Subject: Re: Regex with a varrying number of captures
Message-Id: <d93u4m$923$1@redhat2.bham.ac.uk>
Bart Lateur wrote:
> Joe Gottman wrote:
>
>
>>I am parsing a file with several lines of the form
>> keyword : value1 value2 ... valueN
>>
>>What is the easiest way for me to write a regex that will capture all of the
>>values? my first pass was
>> /^ \s* keyword \s* : (?: \s* (\w+) \b)+/x
>>
>>but this only captures the last value.
>
> The only solution that I think works reasonably well, is a two step
> approach: first match the whole list, and second split up the match into
> its parts. For example, like this (though there are other approches, for
> example using split):
>
> if(/^ \s* keyword \s* : ((?: \s* \w+ \b)+)/x) {
> @parts = $1 =~ /\w+/g;
> }
It is worth mentioning that rather than capturing and reprocessing $1
you can take advantage of the behaviour of //g in a scalar context.
if(/^ \s* keyword \s* :/gx) {
@parts = /\G \s* (\w+)/g;
}
Note - although I say this technique is worthy mention I probably
wouldn't use it here because although it's equivalent to Bart's solution
I would actually prefer to see an end-of-line anchor in Bart's solution.
if(/^ \s* keyword \s* : ([\s\w]*)$/x) {
@parts = $1 =~ /\w+/g;
}
> Yes, that is indeed making perl do the same match twice.
Of course. But as I show above the first match can actually be somewhat
simpler.
If you are feeling particularly obscure you can combine the two
techniques by using lookahead to set pos() to the middle of a pattern match.
if(/^ \s* keyword \s* : (?=[\s\w]*$)/gx) {
@parts = /\w+/g;
}
This saves the expense of performing the string copy at the expense of
being rather harder to comprehend.
------------------------------
Date: 6 Apr 2001 21:33:47 GMT (Last modified)
From: Perl-Users-Request@ruby.oce.orst.edu (Perl-Users-Digest Admin)
Subject: Digest Administrivia (Last modified: 6 Apr 01)
Message-Id: <null>
Administrivia:
#The Perl-Users Digest is a retransmission of the USENET newsgroup
#comp.lang.perl.misc. For subscription or unsubscription requests, send
#the single line:
#
# subscribe perl-users
#or:
# unsubscribe perl-users
#
#to almanac@ruby.oce.orst.edu.
NOTE: due to the current flood of worm email banging on ruby, the smtp
server on ruby has been shut off until further notice.
To submit articles to comp.lang.perl.announce, send your article to
clpa@perl.com.
#To request back copies (available for a week or so), send your request
#to almanac@ruby.oce.orst.edu with the command "send perl-users x.y",
#where x is the volume number and y is the issue number.
#For other requests pertaining to the digest, send mail to
#perl-users-request@ruby.oce.orst.edu. Do not waste your time or mine
#sending perl questions to the -request address, I don't have time to
#answer them even if I did know the answer.
------------------------------
End of Perl-Users Digest V10 Issue 8186
***************************************