[11370] in Perl-Users-Digest
Perl-Users Digest, Issue: 4970 Volume: 8
daemon@ATHENA.MIT.EDU (Perl-Users Digest)
Fri Feb 26 11:27:32 1999
Date: Fri, 26 Feb 99 08:24:09 -0800
From: Perl-Users Digest <Perl-Users-Request@ruby.OCE.ORST.EDU>
To: Perl-Users@ruby.OCE.ORST.EDU (Perl-Users Digest)
Perl-Users Digest Fri, 26 Feb 1999 Volume: 8 Number: 4970
Today's topics:
Re: FAQ 4.61: How can I get the unique keys from two ha (Bart Lateur)
Re: FAQ 4.61: How can I get the unique keys from two ha (Abigail)
Re: FAQ 4.61: How can I get the unique keys from two ha (Bart Lateur)
FAQ 4.62: How can I store a multidimensional array in a <perlfaq-suggestions@perl.com>
FAQ 4.63: How can I make my hash remember the order I p <perlfaq-suggestions@perl.com>
FAQ 4.64: Why does passing a subroutine an undefined el <perlfaq-suggestions@perl.com>
FAQ 4.65: How can I make the Perl equivalent of a C str <perlfaq-suggestions@perl.com>
FAQ 4.66: How can I use a reference as a hash key? <perlfaq-suggestions@perl.com>
FAQ 4.67: How do I handle binary data correctly? <perlfaq-suggestions@perl.com>
FAQ 4.68: How do I determine whether a scalar is a numb <perlfaq-suggestions@perl.com>
FAQ 4.69: How do I keep persistent data across program <perlfaq-suggestions@perl.com>
FAQ 4.70: How do I print out or copy a recursive data s <perlfaq-suggestions@perl.com>
FAQ 4.71: How do I define methods for every class/objec <perlfaq-suggestions@perl.com>
FAQ 4.72: How do I verify a credit card checksum? <perlfaq-suggestions@perl.com>
FAQ 4.73: How do I pack arrays of doubles or floats for <perlfaq-suggestions@perl.com>
FAQ 6.10: How do I use a regular expression to strip C <perlfaq-suggestions@perl.com>
FAQ 6.11: Can I use Perl regular expressions to match b <perlfaq-suggestions@perl.com>
FAQ 6.12: What does it mean that regexps are greedy? H <perlfaq-suggestions@perl.com>
FAQ 6.13: How do I process each word on each line? <perlfaq-suggestions@perl.com>
FAQ 6.14: How can I print out a word-frequency or line- <perlfaq-suggestions@perl.com>
FAQ 6.15: How can I do approximate matching? <perlfaq-suggestions@perl.com>
FAQ 6.16: How do I efficiently match many regular expre <perlfaq-suggestions@perl.com>
FAQ 6.17: Why don't word-boundary searches with C<\b> w <perlfaq-suggestions@perl.com>
FAQ 6.18: Why does using $&, $`, or $' slow my program <perlfaq-suggestions@perl.com>
FAQ 6.19: What good is C<\G> in a regular expression? <perlfaq-suggestions@perl.com>
FAQ 6.1: How can I hope to use regular expressions with <perlfaq-suggestions@perl.com>
Special: Digest Administrivia (Last modified: 12 Dec 98 (Perl-Users-Digest Admin)
----------------------------------------------------------------------
Date: Tue, 23 Feb 1999 21:04:42 GMT
From: bart.lateur@skynet.be (Bart Lateur)
Subject: Re: FAQ 4.61: How can I get the unique keys from two hashes?
Message-Id: <36d61362.2741196@news.skynet.be>
Tom Christiansen wrote:
> How can I get the unique keys from two hashes?
>
> First you extract the keys from the hashes into arrays, and then solve
> the uniquifying the array problem described above. For example:
>
> %seen = ();
> for $element (keys(%foo), keys(%bar)) {
> $seen{$element}++;
> }
> @uniq = keys %seen;
As an aside: the above could also be rewritten as:
{
my %combined = ( %foo, %bar );
@uniq = keys %seen;
}
But, I'm not sure I understand the problem. I would have thought that
what you want is those keys that are in one hash but not the other, or
vice versa, or both. This code doesn't do that.
My solution maintains more "interesting" data in the %seen hash, so you
CAN extract the info I mentioned. The trick is to use bit flags.
{
my $mask = 1;
undef %seen;
foreach $hash (\%foo,\%bar) {
foreach (keys %$hash) {
$seen{$_} |= $mask;
}
} continue {
$mask *=2;
}
}
And it's extensible with more hashes, too!
If you want the elements in %foo but not in %bar, just use
@ary = grep { $seen{$_} ==1 } keys %seen;
Unique to %bar? Compare to 2. Common to both? Compare to 3.
Bart.
------------------------------
Date: 24 Feb 1999 01:02:30 GMT
From: abigail@fnx.com (Abigail)
Subject: Re: FAQ 4.61: How can I get the unique keys from two hashes?
Message-Id: <7avj36$ao5$5@client2.news.psi.net>
Bart Lateur (bart.lateur@skynet.be) wrote on MMII September MCMXCIII in
<URL:news:36d61362.2741196@news.skynet.be>:
--
-- My solution maintains more "interesting" data in the %seen hash, so you
-- CAN extract the info I mentioned. The trick is to use bit flags.
--
-- {
-- my $mask = 1;
-- undef %seen;
-- foreach $hash (\%foo,\%bar) {
-- foreach (keys %$hash) {
-- $seen{$_} |= $mask;
-- }
-- } continue {
-- $mask *=2;
-- }
-- }
How utterly complicated.
You want the symmetrical difference. Those elements in %foo that are not
in %bar, and those elements of %bar that are not in %foo. Don't be clever.
Just code out what I just said:
@sym_diff = (grep {!exists $bar {$_}} keys %foo),
(grep {!exists $foo {$_}} keys %bar);
Abigail
--
perl -wle 'print "Prime" if (1 x shift) !~ /^1?$|^(11+?)\1+$/'
------------------------------
Date: Wed, 24 Feb 1999 09:42:39 GMT
From: bart.lateur@skynet.be (Bart Lateur)
Subject: Re: FAQ 4.61: How can I get the unique keys from two hashes?
Message-Id: <36d5c439.1220927@news.skynet.be>
Abigail wrote:
>How utterly complicated.
Not much more complicated than the original, but far more useful for
some applications.
>You want the symmetrical difference. Those elements in %foo that are not
>in %bar, and those elements of %bar that are not in %foo.
*OR*. Separate sets.
> Don't be clever.
>Just code out what I just said:
>
>@sym_diff = (grep {!exists $bar {$_}} keys %foo),
> (grep {!exists $foo {$_}} keys %bar);
Except my solution returns it ALL. You'd have to redo it if you want
more than one subset. Plus, I find bitmasks quite easy to grasp.
And what about three hashes? Want those elements in %foo but neither in
%bar nor in %baz? Or in %bar and in %baz, but not in %foo? My solution
scales up nicely. Yours doesn't.
Bart.
------------------------------
Date: 23 Feb 1999 01:13:50 -0700
From: Tom Christiansen <perlfaq-suggestions@perl.com>
Subject: FAQ 4.62: How can I store a multidimensional array in a DBM file?
Message-Id: <36d2633e@csnews>
(This excerpt from perlfaq4 - Data Manipulation
($Revision: 1.43 $, $Date: 1999/01/26 09:57:23 $)
part of the standard set of documentation included with every
valid Perl distribution, like the one on your system.
See also http://language.perl.com/newdocs/pod/perlfaq4.html
if your negligent system adminstrator has been remiss in his duties.)
How can I store a multidimensional array in a DBM file?
Either stringify the structure yourself (no fun), or else get the MLDBM
(which uses Data::Dumper) module from CPAN and layer it on top of either
DB_File or GDBM_File.
--
There is no problem so small that it can't be blamed on Datakit --Andrew Hume
------------------------------
Date: 23 Feb 1999 02:13:53 -0700
From: Tom Christiansen <perlfaq-suggestions@perl.com>
Subject: FAQ 4.63: How can I make my hash remember the order I put elements into it?
Message-Id: <36d27151@csnews>
(This excerpt from perlfaq4 - Data Manipulation
($Revision: 1.43 $, $Date: 1999/01/26 09:57:23 $)
part of the standard set of documentation included with every
valid Perl distribution, like the one on your system.
See also http://language.perl.com/newdocs/pod/perlfaq4.html
if your negligent system adminstrator has been remiss in his duties.)
How can I make my hash remember the order I put elements into it?
Use the Tie::IxHash from CPAN.
use Tie::IxHash;
tie(%myhash, Tie::IxHash);
for ($i=0; $i<20; $i++) {
$myhash{$i} = 2*$i;
}
@keys = keys %myhash;
# @keys = (0,1,2,3,...)
--
Interestingly enough, since subroutine declarations can come anywhere,
you wouldn't have to put BEGIN {} at the beginning, nor END {} at the
end. Interesting, no? I wonder if Henry would like it. :-) --lwall
------------------------------
Date: 23 Feb 1999 03:14:01 -0700
From: Tom Christiansen <perlfaq-suggestions@perl.com>
Subject: FAQ 4.64: Why does passing a subroutine an undefined element in a hash create it?
Message-Id: <36d27f69@csnews>
(This excerpt from perlfaq4 - Data Manipulation
($Revision: 1.43 $, $Date: 1999/01/26 09:57:23 $)
part of the standard set of documentation included with every
valid Perl distribution, like the one on your system.
See also http://language.perl.com/newdocs/pod/perlfaq4.html
if your negligent system adminstrator has been remiss in his duties.)
Why does passing a subroutine an undefined element in a hash create it?
If you say something like:
somefunc($hash{"nonesuch key here"});
Then that element "autovivifies"; that is, it springs into existence
whether you store something there or not. That's because functions get
scalars passed in by reference. If somefunc() modifies `$_[0]', it has
to be ready to write it back into the caller's version.
This has been fixed as of perl5.004.
Normally, merely accessing a key's value for a nonexistent key does
*not* cause that key to be forever there. This is different than awk's
behavior.
--
"Perl5, surprisingly, makes it very easy to do OO programming. I suspect
that it does this much better than Larry ever intended."
--Dean Roehrich in <1994Oct5.140720.1511@driftwood.cray.com>
------------------------------
Date: 23 Feb 1999 04:14:08 -0700
From: Tom Christiansen <perlfaq-suggestions@perl.com>
Subject: FAQ 4.65: How can I make the Perl equivalent of a C structure/C++ class/hash or array of hashes or arrays?
Message-Id: <36d28d80@csnews>
(This excerpt from perlfaq4 - Data Manipulation
($Revision: 1.43 $, $Date: 1999/01/26 09:57:23 $)
part of the standard set of documentation included with every
valid Perl distribution, like the one on your system.
See also http://language.perl.com/newdocs/pod/perlfaq4.html
if your negligent system adminstrator has been remiss in his duties.)
How can I make the Perl equivalent of a C structure/C++ class/hash or array of hashes or arrays?
Usually a hash ref, perhaps like this:
$record = {
NAME => "Jason",
EMPNO => 132,
TITLE => "deputy peon",
AGE => 23,
SALARY => 37_000,
PALS => [ "Norbert", "Rhys", "Phineas"],
};
References are documented in the perlref manpage and the upcoming the
perlreftut manpage. Examples of complex data structures are given in the
perldsc manpage and the perllol manpage. Examples of structures and
object-oriented classes are in the perltoot manpage.
--
#ifdef USE_STD_STDIO /* Here is some breathtakingly efficient cheating */
--Larry Wall, from sv.c in the v5.0 perl distribution
------------------------------
Date: 23 Feb 1999 05:14:24 -0700
From: Tom Christiansen <perlfaq-suggestions@perl.com>
Subject: FAQ 4.66: How can I use a reference as a hash key?
Message-Id: <36d29ba0@csnews>
(This excerpt from perlfaq4 - Data Manipulation
($Revision: 1.43 $, $Date: 1999/01/26 09:57:23 $)
part of the standard set of documentation included with every
valid Perl distribution, like the one on your system.
See also http://language.perl.com/newdocs/pod/perlfaq4.html
if your negligent system adminstrator has been remiss in his duties.)
How can I use a reference as a hash key?
You can't do this directly, but you could use the standard Tie::Refhash
module distributed with perl.
--
Even if you aren't in doubt, consider the mental welfare of the person who
has to maintain the code after you, and who will probably put parens in
the wrong place. --Larry Wall in the perl man page
------------------------------
Date: 23 Feb 1999 06:15:05 -0700
From: Tom Christiansen <perlfaq-suggestions@perl.com>
Subject: FAQ 4.67: How do I handle binary data correctly?
Message-Id: <36d2a9d9@csnews>
(This excerpt from perlfaq4 - Data Manipulation
($Revision: 1.43 $, $Date: 1999/01/26 09:57:23 $)
part of the standard set of documentation included with every
valid Perl distribution, like the one on your system.
See also http://language.perl.com/newdocs/pod/perlfaq4.html
if your negligent system adminstrator has been remiss in his duties.)
How do I handle binary data correctly?
Perl is binary clean, so this shouldn't be a problem. For example, this
works fine (assuming the files are found):
if (`cat /vmunix` =~ /gzip/) {
print "Your kernel is GNU-zip enabled!\n";
}
On some legacy systems, however, you have to play tedious games with
"text" versus "binary" files. See the section on "binmode" in the
perlfunc manpage, or the upcoming the perlopentut manpage manpage.
If you're concerned about 8-bit ASCII data, then see the perllocale
manpage.
If you want to deal with multibyte characters, however, there are some
gotchas. See the section on Regular Expressions.
--
"I have many friends who question authority. For some reason most of 'em
limit themselves to rhetorical questions."
--Larry Wall
------------------------------
Date: 23 Feb 1999 06:57:14 -0700
From: Tom Christiansen <perlfaq-suggestions@perl.com>
Subject: FAQ 4.68: How do I determine whether a scalar is a number/whole/integer/float?
Message-Id: <36d2b3ba@csnews>
(This excerpt from perlfaq4 - Data Manipulation
($Revision: 1.43 $, $Date: 1999/01/26 09:57:23 $)
part of the standard set of documentation included with every
valid Perl distribution, like the one on your system.
See also http://language.perl.com/newdocs/pod/perlfaq4.html
if your negligent system adminstrator has been remiss in his duties.)
How do I determine whether a scalar is a number/whole/integer/float?
Assuming that you don't care about IEEE notations like "NaN" or
"Infinity", you probably just want to use a regular expression.
if (/\D/) { print "has nondigits\n" }
if (/^\d+$/) { print "is a whole number\n" }
if (/^-?\d+$/) { print "is an integer\n" }
if (/^[+-]?\d+$/) { print "is a +/- integer\n" }
if (/^-?\d+\.?\d*$/) { print "is a real number\n" }
if (/^-?(?:\d+(?:\.\d*)?|\.\d+)$/) { print "is a decimal number" }
if (/^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/)
{ print "a C float" }
If you're on a POSIX system, Perl's supports the `POSIX::strtod'
function. Its semantics are somewhat cumbersome, so here's a `getnum'
wrapper function for more convenient access. This function takes a
string and returns the number it found, or `undef' for input that isn't
a C float. The `is_numeric' function is a front end to `getnum' if you
just want to say, ``Is this a float?''
sub getnum {
use POSIX qw(strtod);
my $str = shift;
$str =~ s/^\s+//;
$str =~ s/\s+$//;
$! = 0;
my($num, $unparsed) = strtod($str);
if (($str eq '') || ($unparsed != 0) || $!) {
return undef;
} else {
return $num;
}
}
sub is_numeric { defined &getnum }
Or you could check out http://www.perl.com/CPAN/modules/by-
module/String/String-Scanf-1.1.tar.gz instead. The POSIX module (part of
the standard Perl distribution) provides the `strtol' and `strtod' for
converting strings to double and longs, respectively.
--
There ain't nothin' in this world that's worth being a snot over.
--Larry Wall in <1992Aug19.041614.6963@netlabs.com>
------------------------------
Date: 23 Feb 1999 07:02:43 -0700
From: Tom Christiansen <perlfaq-suggestions@perl.com>
Subject: FAQ 4.69: How do I keep persistent data across program calls?
Message-Id: <36d2b503@csnews>
(This excerpt from perlfaq4 - Data Manipulation
($Revision: 1.43 $, $Date: 1999/01/26 09:57:23 $)
part of the standard set of documentation included with every
valid Perl distribution, like the one on your system.
See also http://language.perl.com/newdocs/pod/perlfaq4.html
if your negligent system adminstrator has been remiss in his duties.)
How do I keep persistent data across program calls?
For some specific applications, you can use one of the DBM modules. See
the AnyDBM_File manpage. More generically, you should consult the
FreezeThaw, Storable, or Class::Eroot modules from CPAN. Here's one
example using Storable's `store' and `retrieve' functions:
use Storable;
store(\%hash, "filename");
# later on...
$href = retrieve("filename"); # by ref
%hash = %{ retrieve("filename") }; # direct to hash
--
During the next two hours, the VAX will be going up and down several
times, often with lin~po_~{po ~poz~ppo\~{ o n~po_^G~{o[po ~y
oodsou>#w4k**
n~po_^G~{ol;lkld;f;g;dd;po\~{o
------------------------------
Date: 23 Feb 1999 07:44:38 -0700
From: Tom Christiansen <perlfaq-suggestions@perl.com>
Subject: FAQ 4.70: How do I print out or copy a recursive data structure?
Message-Id: <36d2bed6@csnews>
(This excerpt from perlfaq4 - Data Manipulation
($Revision: 1.43 $, $Date: 1999/01/26 09:57:23 $)
part of the standard set of documentation included with every
valid Perl distribution, like the one on your system.
See also http://language.perl.com/newdocs/pod/perlfaq4.html
if your negligent system adminstrator has been remiss in his duties.)
How do I print out or copy a recursive data structure?
The Data::Dumper module on CPAN (or the 5.005 release of Perl) is great
for printing out data structures. The Storable module, found on CPAN,
provides a function called `dclone' that recursively copies its
argument.
use Storable qw(dclone);
$r2 = dclone($r1);
Where $r1 can be a reference to any kind of data structure you'd like.
It will be deeply copied. Because `dclone' takes and returns references,
you'd have to add extra punctuation if you had a hash of arrays that you
wanted to copy.
%newhash = %{ dclone(\%oldhash) };
--
"The road to hell is paved with melting snowballs."
--Larry Wall in <1992Jul2.222039.26476@netlabs.com>
------------------------------
Date: 23 Feb 1999 08:44:40 -0700
From: Tom Christiansen <perlfaq-suggestions@perl.com>
Subject: FAQ 4.71: How do I define methods for every class/object?
Message-Id: <36d2cce8@csnews>
(This excerpt from perlfaq4 - Data Manipulation
($Revision: 1.43 $, $Date: 1999/01/26 09:57:23 $)
part of the standard set of documentation included with every
valid Perl distribution, like the one on your system.
See also http://language.perl.com/newdocs/pod/perlfaq4.html
if your negligent system adminstrator has been remiss in his duties.)
How do I define methods for every class/object?
Use the UNIVERSAL class (see the UNIVERSAL manpage).
--
"Everything you said about Plan 9 is wrong"
-- Rob Pike, letting a speaker have it
------------------------------
Date: 23 Feb 1999 09:44:47 -0700
From: Tom Christiansen <perlfaq-suggestions@perl.com>
Subject: FAQ 4.72: How do I verify a credit card checksum?
Message-Id: <36d2daff@csnews>
(This excerpt from perlfaq4 - Data Manipulation
($Revision: 1.43 $, $Date: 1999/01/26 09:57:23 $)
part of the standard set of documentation included with every
valid Perl distribution, like the one on your system.
See also http://language.perl.com/newdocs/pod/perlfaq4.html
if your negligent system adminstrator has been remiss in his duties.)
How do I verify a credit card checksum?
Get the Business::CreditCard module from CPAN.
--
"Of course, someone who knows more about this will correct me if I'm wrong,
and someone who knows less will correct me if I'm right."
--David Palmer (palmer@tybalt.caltech.edu)
------------------------------
Date: 23 Feb 1999 10:44:50 -0700
From: Tom Christiansen <perlfaq-suggestions@perl.com>
Subject: FAQ 4.73: How do I pack arrays of doubles or floats for XS code?
Message-Id: <36d2e912@csnews>
(This excerpt from perlfaq4 - Data Manipulation
($Revision: 1.43 $, $Date: 1999/01/26 09:57:23 $)
part of the standard set of documentation included with every
valid Perl distribution, like the one on your system.
See also http://language.perl.com/newdocs/pod/perlfaq4.html
if your negligent system adminstrator has been remiss in his duties.)
How do I pack arrays of doubles or floats for XS code?
The kgbpack.c code in the PGPLOT module on CPAN does just this. If
you're doing a lot of float or double processing, consider using the PDL
module from CPAN instead--it makes number-crunching easy.
--
X-Windows: graphics hacking :: roman numerals : sqrt(pi)
--Jamie Zawinski
------------------------------
Date: 25 Feb 1999 05:27:47 -0700
From: Tom Christiansen <perlfaq-suggestions@perl.com>
Subject: FAQ 6.10: How do I use a regular expression to strip C style comments from a file?
Message-Id: <36d541c3@csnews>
(This excerpt from perlfaq6 - Regexps
($Revision: 1.25 $, $Date: 1999/01/08 04:50:47 $)
part of the standard set of documentation included with every
valid Perl distribution, like the one on your system.
See also http://language.perl.com/newdocs/pod/perlfaq6.html
if your negligent system adminstrator has been remiss in his duties.)
How do I use a regular expression to strip C style comments from a file?
While this actually can be done, it's much harder than you'd think. For
example, this one-liner
perl -0777 -pe 's{/\*.*?\*/}{}gs' foo.c
will work in many but not all cases. You see, it's too simple-minded for
certain kinds of C programs, in particular, those with what appear to be
comments in quoted strings. For that, you'd need something like this,
created by Jeffrey Friedl:
$/ = undef;
$_ = <>;
s#/\*[^*]*\*+([^/*][^*]*\*+)*/|("(\\.|[^"\\])*"|'(\\.|[^'\\])*'|\n+|.[^/"'\\]*)#$2#g;
print;
This could, of course, be more legibly written with the `/x' modifier,
adding whitespace and comments.
--
If I allowed "next $label" then I'd also have to allow "goto $label",
and I don't think you really want that... :-) [now works in perl5!]
--Larry Wall in <1991Mar11.230002.27271@jpl-devvax.jpl.nasa.gov>
------------------------------
Date: 25 Feb 1999 07:57:53 -0700
From: Tom Christiansen <perlfaq-suggestions@perl.com>
Subject: FAQ 6.11: Can I use Perl regular expressions to match balanced text?
Message-Id: <36d564f1@csnews>
(This excerpt from perlfaq6 - Regexps
($Revision: 1.25 $, $Date: 1999/01/08 04:50:47 $)
part of the standard set of documentation included with every
valid Perl distribution, like the one on your system.
See also http://language.perl.com/newdocs/pod/perlfaq6.html
if your negligent system adminstrator has been remiss in his duties.)
Can I use Perl regular expressions to match balanced text?
Although Perl regular expressions are more powerful than "mathematical"
regular expressions, because they feature conveniences like
backreferences (`\1' and its ilk), they still aren't powerful enough.
You still need to use non-regexp techniques to parse balanced text, such
as the text enclosed between matching parentheses or braces, for
example.
An elaborate subroutine (for 7-bit ASCII only) to pull out balanced and
possibly nested single chars, like ``' and `'', `{' and `}', or `(' and
`)' can be found in
http://www.perl.com/CPAN/authors/id/TOMC/scripts/pull_quotes.gz .
The C::Scan module from CPAN contains such subs for internal usage, but
they are undocumented.
--
Does the same as the system call of that name.
If you don't know what it does, don't worry about it.
--Larry Wall in the perl man page regarding chroot(2)
------------------------------
Date: 25 Feb 1999 10:28:11 -0700
From: Tom Christiansen <perlfaq-suggestions@perl.com>
Subject: FAQ 6.12: What does it mean that regexps are greedy? How can I get around it?
Message-Id: <36d5882b@csnews>
(This excerpt from perlfaq6 - Regexps
($Revision: 1.25 $, $Date: 1999/01/08 04:50:47 $)
part of the standard set of documentation included with every
valid Perl distribution, like the one on your system.
See also http://language.perl.com/newdocs/pod/perlfaq6.html
if your negligent system adminstrator has been remiss in his duties.)
What does it mean that regexps are greedy? How can I get around it?
Most people mean that greedy regexps match as much as they can.
Technically speaking, it's actually the quantifiers (`?', `*', `+',
`{}') that are greedy rather than the whole pattern; Perl prefers local
greed and immediate gratification to overall greed. To get non-greedy
versions of the same quantifiers, use (`??', `*?', `+?', `{}?').
An example:
$s1 = $s2 = "I am very very cold";
$s1 =~ s/ve.*y //; # I am cold
$s2 =~ s/ve.*?y //; # I am very cold
Notice how the second substitution stopped matching as soon as it
encountered "y ". The `*?' quantifier effectively tells the regular
expression engine to find a match as quickly as possible and pass
control on to whatever is next in line, like you would if you were
playing hot potato.
--
*** The previous line contains the naughty word "$&".\n
if /(ibm|apple|awk)/; # :-)
--Larry Wall in the perl man page
------------------------------
Date: 25 Feb 1999 12:58:17 -0700
From: Tom Christiansen <perlfaq-suggestions@perl.com>
Subject: FAQ 6.13: How do I process each word on each line?
Message-Id: <36d5ab59@csnews>
(This excerpt from perlfaq6 - Regexps
($Revision: 1.25 $, $Date: 1999/01/08 04:50:47 $)
part of the standard set of documentation included with every
valid Perl distribution, like the one on your system.
See also http://language.perl.com/newdocs/pod/perlfaq6.html
if your negligent system adminstrator has been remiss in his duties.)
How do I process each word on each line?
Use the split function:
while (<>) {
foreach $word ( split ) {
# do something with $word here
}
}
Note that this isn't really a word in the English sense; it's just
chunks of consecutive non-whitespace characters.
To work with only alphanumeric sequences, you might consider
while (<>) {
foreach $word (m/(\w+)/g) {
# do something with $word here
}
}
--
"Fanaticism consists of redoubling your efforts when you have forgotten
your aim." --Santayana
------------------------------
Date: 25 Feb 1999 15:28:19 -0700
From: Tom Christiansen <perlfaq-suggestions@perl.com>
Subject: FAQ 6.14: How can I print out a word-frequency or line-frequency summary?
Message-Id: <36d5ce83@csnews>
(This excerpt from perlfaq6 - Regexps
($Revision: 1.25 $, $Date: 1999/01/08 04:50:47 $)
part of the standard set of documentation included with every
valid Perl distribution, like the one on your system.
See also http://language.perl.com/newdocs/pod/perlfaq6.html
if your negligent system adminstrator has been remiss in his duties.)
How can I print out a word-frequency or line-frequency summary?
To do this, you have to parse out each word in the input stream. We'll
pretend that by word you mean chunk of alphabetics, hyphens, or
apostrophes, rather than the non-whitespace chunk idea of a word given
in the previous question:
while (<>) {
while ( /(\b[^\W_\d][\w'-]+\b)/g ) { # misses "`sheep'"
$seen{$1}++;
}
}
while ( ($word, $count) = each %seen ) {
print "$count $word\n";
}
If you wanted to do the same thing for lines, you wouldn't need a
regular expression:
while (<>) {
$seen{$_}++;
}
while ( ($line, $count) = each %seen ) {
print "$count $line";
}
If you want these output in a sorted order, see the section on Hashes.
--
If I had only known, I would have been a locksmith. --Albert Einstein
------------------------------
Date: 25 Feb 1999 17:58:21 -0700
From: Tom Christiansen <perlfaq-suggestions@perl.com>
Subject: FAQ 6.15: How can I do approximate matching?
Message-Id: <36d5f1ad@csnews>
(This excerpt from perlfaq6 - Regexps
($Revision: 1.25 $, $Date: 1999/01/08 04:50:47 $)
part of the standard set of documentation included with every
valid Perl distribution, like the one on your system.
See also http://language.perl.com/newdocs/pod/perlfaq6.html
if your negligent system adminstrator has been remiss in his duties.)
How can I do approximate matching?
See the module String::Approx available from CPAN.
--
I don't know if it's what you want, but it's what you get. :-)
--Larry Wall in <10502@jpl-devvax.JPL.NASA.GOV>
------------------------------
Date: 25 Feb 1999 20:28:23 -0700
From: Tom Christiansen <perlfaq-suggestions@perl.com>
Subject: FAQ 6.16: How do I efficiently match many regular expressions at once?
Message-Id: <36d614d7@csnews>
(This excerpt from perlfaq6 - Regexps
($Revision: 1.25 $, $Date: 1999/01/08 04:50:47 $)
part of the standard set of documentation included with every
valid Perl distribution, like the one on your system.
See also http://language.perl.com/newdocs/pod/perlfaq6.html
if your negligent system adminstrator has been remiss in his duties.)
How do I efficiently match many regular expressions at once?
The following is extremely inefficient:
# slow but obvious way
@popstates = qw(CO ON MI WI MN);
while (defined($line = <>)) {
for $state (@popstates) {
if ($line =~ /\b$state\b/i) {
print $line;
last;
}
}
}
That's because Perl has to recompile all those patterns for each of the
lines of the file. As of the 5.005 release, there's a much better
approach, one which makes use of the new `qr//' operator:
# use spiffy new qr// operator, with /i flag even
use 5.005;
@popstates = qw(CO ON MI WI MN);
@poppats = map { qr/\b$_\b/i } @popstates;
while (defined($line = <>)) {
for $patobj (@poppats) {
print $line if $line =~ /$patobj/;
}
}
--
"Have the appropriate amount of fun." --Larry Wall
------------------------------
Date: 25 Feb 1999 22:58:25 -0700
From: Tom Christiansen <perlfaq-suggestions@perl.com>
Subject: FAQ 6.17: Why don't word-boundary searches with C<\b> work for me?
Message-Id: <36d63801@csnews>
(This excerpt from perlfaq6 - Regexps
($Revision: 1.25 $, $Date: 1999/01/08 04:50:47 $)
part of the standard set of documentation included with every
valid Perl distribution, like the one on your system.
See also http://language.perl.com/newdocs/pod/perlfaq6.html
if your negligent system adminstrator has been remiss in his duties.)
Why don't word-boundary searches with `\b' work for me?
Two common misconceptions are that `\b' is a synonym for `\s+', and that
it's the edge between whitespace characters and non-whitespace
characters. Neither is correct. `\b' is the place between a `\w'
character and a `\W' character (that is, `\b' is the edge of a "word").
It's a zero-width assertion, just like `^', `$', and all the other
anchors, so it doesn't consume any characters. the perlre manpage
describes the behaviour of all the regexp metacharacters.
Here are examples of the incorrect application of `\b', with fixes:
"two words" =~ /(\w+)\b(\w+)/; # WRONG
"two words" =~ /(\w+)\s+(\w+)/; # right
" =matchless= text" =~ /\b=(\w+)=\b/; # WRONG
" =matchless= text" =~ /=(\w+)=/; # right
Although they may not do what you thought they did, `\b' and `\B' can
still be quite useful. For an example of the correct use of `\b', see
the example of matching duplicate words over multiple lines.
An example of using `\B' is the pattern `\Bis\B'. This will find
occurrences of "is" on the insides of words only, as in "thistle", but
not "this" or "island".
--
Mark the differences, moreover,
Between mover, cover, clover;
------------------------------
Date: 26 Feb 1999 01:28:27 -0700
From: Tom Christiansen <perlfaq-suggestions@perl.com>
Subject: FAQ 6.18: Why does using $&, $`, or $' slow my program down?
Message-Id: <36d65b2b@csnews>
(This excerpt from perlfaq6 - Regexps
($Revision: 1.25 $, $Date: 1999/01/08 04:50:47 $)
part of the standard set of documentation included with every
valid Perl distribution, like the one on your system.
See also http://language.perl.com/newdocs/pod/perlfaq6.html
if your negligent system adminstrator has been remiss in his duties.)
Why does using $&, $`, or $' slow my program down?
Because once Perl sees that you need one of these variables anywhere in
the program, it has to provide them on each and every pattern match. The
same mechanism that handles these provides for the use of $1, $2, etc.,
so you pay the same price for each regexp that contains capturing
parentheses. But if you never use $&, etc., in your script, then regexps
*without* capturing parentheses won't be penalized. So 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.
--
"Sex education classes in our public schools are promoting incest."
--Jimmy Swaggart, TV preacher, self-described pornography addict who paid
prostitutes to commit "pornographic acts"; hypocrite
------------------------------
Date: 26 Feb 1999 03:58:37 -0700
From: Tom Christiansen <perlfaq-suggestions@perl.com>
Subject: FAQ 6.19: What good is C<\G> in a regular expression?
Message-Id: <36d67e5d@csnews>
(This excerpt from perlfaq6 - Regexps
($Revision: 1.25 $, $Date: 1999/01/08 04:50:47 $)
part of the standard set of documentation included with every
valid Perl distribution, like the one on your system.
See also http://language.perl.com/newdocs/pod/perlfaq6.html
if your negligent system adminstrator has been remiss in his duties.)
What good is `\G' in a regular expression?
The notation `\G' is used in a match or substitution in conjunction the
`/g' modifier (and ignored if there's no `/g') to anchor the regular
expression to the point just past where the last match occurred, i.e.
the pos() point. A failed match resets the position of `\G' unless the
`/c' modifier is in effect.
For example, suppose you had a line of text quoted in standard mail and
Usenet notation, (that is, with leading `>' characters), and you want
change each leading `>' into a corresponding `:'. You could do so in
this way:
s/^(>+)/':' x length($1)/gem;
Or, using `\G', the much simpler (and faster):
s/\G>/:/g;
A more sophisticated use might involve a tokenizer. The following lex-
like example is courtesy of Jeffrey Friedl. It did not work in 5.003 due
to bugs in that release, but does work in 5.004 or better. (Note the use
of `/c', which prevents a failed match with `/g' from resetting the
search position back to the beginning of the string.)
while (<>) {
chomp;
PARSER: {
m/ \G( \d+\b )/gcx && do { print "number: $1\n"; redo; };
m/ \G( \w+ )/gcx && do { print "word: $1\n"; redo; };
m/ \G( \s+ )/gcx && do { print "space: $1\n"; redo; };
m/ \G( [^\w\d]+ )/gcx && do { print "other: $1\n"; redo; };
}
}
Of course, that could have been written as
while (<>) {
chomp;
PARSER: {
if ( /\G( \d+\b )/gcx {
print "number: $1\n";
redo PARSER;
}
if ( /\G( \w+ )/gcx {
print "word: $1\n";
redo PARSER;
}
if ( /\G( \s+ )/gcx {
print "space: $1\n";
redo PARSER;
}
if ( /\G( [^\w\d]+ )/gcx {
print "other: $1\n";
redo PARSER;
}
}
}
But then you lose the vertical alignment of the regular expressions.
--
Man is the best computer we can put aboard a spacecraft ... and the
only one that can be mass produced with unskilled labor.
--Wernher von Braun
------------------------------
Date: 24 Feb 1999 06:57:04 -0700
From: Tom Christiansen <perlfaq-suggestions@perl.com>
Subject: FAQ 6.1: How can I hope to use regular expressions without creating illegible and unmaintainable code?
Message-Id: <36d40530@csnews>
(This excerpt from perlfaq6 - Regexps
($Revision: 1.25 $, $Date: 1999/01/08 04:50:47 $)
part of the standard set of documentation included with every
valid Perl distribution, like the one on your system.
See also http://language.perl.com/newdocs/pod/perlfaq6.html
if your negligent system adminstrator has been remiss in his duties.)
How can I hope to use regular expressions without creating illegible and unmaintainable code?
Three techniques can make regular expressions maintainable and
understandable.
Comments Outside the Regexp
Describe what you're doing and how you're doing it, using normal
Perl comments.
# turn the line into the first word, a colon, and the
# number of characters on the rest of the line
s/^(\w+)(.*)/ lc($1) . ":" . length($2) /meg;
Comments Inside the Regexp
The `/x' modifier causes whitespace to be ignored in a regexp
pattern (except in a character class), and also allows you to use
normal comments there, too. As you can imagine, whitespace and
comments help a lot.
`/x' lets you turn this:
s{<(?:[^>'"]*|".*?"|'.*?')+>}{}gs;
into this:
s{ < # opening angle bracket
(?: # Non-backreffing grouping paren
[^>'"] * # 0 or more things that are neither > nor ' nor "
| # or else
".*?" # a section between double quotes (stingy match)
| # or else
'.*?' # a section between single quotes (stingy match)
) + # all occurring one or more times
> # closing angle bracket
}{}gsx; # replace with nothing, i.e. delete
It's still not quite so clear as prose, but it is very useful for
describing the meaning of each part of the pattern.
Different Delimiters
While we normally think of patterns as being delimited with `/'
characters, they can be delimited by almost any character. the
perlre manpage describes this. For example, the `s///' above uses
braces as delimiters. Selecting another delimiter can avoid quoting
the delimiter within the pattern:
s/\/usr\/local/\/usr\/share/g; # bad delimiter choice
s#/usr/local#/usr/share#g; # better
--
"A ship then new they built for him/of mithril and of elven glass"
--Larry Wall in perl.c from the v5.0 perl distribution,
citing Bilbo from Tolkien's Lord of the Rings trilogy
------------------------------
Date: 12 Dec 98 21:33:47 GMT (Last modified)
From: Perl-Request@ruby.oce.orst.edu (Perl-Users-Digest Admin)
Subject: Special: Digest Administrivia (Last modified: 12 Dec 98)
Message-Id: <null>
Administrivia:
Well, after 6 months, here's the answer to the quiz: what do we do about
comp.lang.perl.moderated. Answer: nothing.
]From: Russ Allbery <rra@stanford.edu>
]Date: 21 Sep 1998 19:53:43 -0700
]Subject: comp.lang.perl.moderated available via e-mail
]
]It is possible to subscribe to comp.lang.perl.moderated as a mailing list.
]To do so, send mail to majordomo@eyrie.org with "subscribe clpm" in the
]body. Majordomo will then send you instructions on how to confirm your
]subscription. This is provided as a general service for those people who
]cannot receive the newsgroup for whatever reason or who just prefer to
]receive messages via e-mail.
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.
To submit articles to comp.lang.perl.misc (and this Digest), send your
article to perl-users@ruby.oce.orst.edu.
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.
The Meta-FAQ, an article containing information about the FAQ, is
available by requesting "send perl-users meta-faq". The real FAQ, as it
appeared last in the newsgroup, can be retrieved with the request "send
perl-users FAQ". Due to their sizes, neither the Meta-FAQ nor the FAQ
are included in the digest.
The "mini-FAQ", which is an updated version of the Meta-FAQ, is
available by requesting "send perl-users mini-faq". It appears twice
weekly in the group, but is not distributed in the digest.
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 V8 Issue 4970
**************************************