develooper Front page | perl.perl5.porters | Postings from April 2000

Revised candidate for perlretut.pod

From:
Mark Kvale
Date:
April 11, 2000 17:40
Subject:
Revised candidate for perlretut.pod
Message ID:
200004120039.e3C0dab05777@phy.ucsf.edu
Here is the revised candidate for perlretut.pod.  The patch against the
original is below, or if you would rather download the new version, it
can be found at

http://keck.ucsf.edu/~kvale/perlretut.pod

I'd like to thank Peter Haworth, Ronald J. Kimball, Joe Smith and
especially Jeff Pinyan for many helpful comments.

        -Mark


ivy 181%  diff -c perlretut.pod.orig perlretut.pod
*** perlretut.pod.orig	Tue Apr 11 17:25:46 2000
--- perlretut.pod	Tue Apr 11 16:46:20 2000
***************
*** 60,110 ****
      "Hello World" =~ /World/;  # matches
  
  What is this perl statement all about? C<"Hello World"> is a simple
! double quoted string.  C<World> is the regular expression and the C<//>
! enclosing C</World/> says to search a string for a match.  The operator
! C<=~> associates the string with the regexp match and produces a true
! value if the regexp matched, or false if the regexp did not match.  In
! our case, C<World> matches the second word in C<"Hello World">, so the
! expression is true.  Expressions like this are useful in conditionals:
  
      if ("Hello World" =~ /World/) {
!         print "It matches\n';
      }
      else {
!         print "It doesn't match\n';
      }
  
! The sense of the match can be reversed by using C<!~> operator:
  
      if ("Hello World" !~ /World/) {
!         print "It doesn't match\n';
      }
      else {
!         print "It matches\n';
      }
  
  The literal string in the regexp can be replaced by a variable:
  
      $greeting = "World";
      if ("Hello World" =~ /$greeting/) {
!         print "It matches\n';
      }
      else {
!         print "It doesn't match\n';
      }
  
! And if you're matching against the special default variable C<$_>, the
  C<$_ =~> part can be omitted:
  
      $_ = "Hello World";
      if (/World/) {
!         print "It matches\n';
      }
      else {
!         print "It doesn't match\n';
      }
  
! Let's consider these statements:
  
      "Hello World" =~ /world/;  # doesn't match
      "Hello World" =~ /o W/;    # matches
--- 60,124 ----
      "Hello World" =~ /World/;  # matches
  
  What is this perl statement all about? C<"Hello World"> is a simple
! double quoted string.  C<World> is the regular expression and the
! C<//> enclosing C</World/> tells perl to search a string for a match.
! The operator C<=~> associates the string with the regexp match and
! produces a true value if the regexp matched, or false if the regexp
! did not match.  In our case, C<World> matches the second word in
! C<"Hello World">, so the expression is true.  Expressions like this
! are useful in conditionals:
  
      if ("Hello World" =~ /World/) {
!         print "It matches\n";
      }
      else {
!         print "It doesn't match\n";
      }
  
! There are useful variations on this theme.  The sense of the match can
! be reversed by using C<!~> operator:
  
      if ("Hello World" !~ /World/) {
!         print "It doesn't match\n";
      }
      else {
!         print "It matches\n";
      }
  
  The literal string in the regexp can be replaced by a variable:
  
      $greeting = "World";
      if ("Hello World" =~ /$greeting/) {
!         print "It matches\n";
      }
      else {
!         print "It doesn't match\n";
      }
  
! If you're matching against the special default variable C<$_>, the
  C<$_ =~> part can be omitted:
  
      $_ = "Hello World";
      if (/World/) {
!         print "It matches\n";
      }
      else {
!         print "It doesn't match\n";
      }
  
! And finally, the C<//> default delimiters for a match can be changed
! to arbitrary delimiters by putting an C<'m'> out front:
! 
!     "Hello World" =~ m!World!;   # matches, delimited by '!'
!     "Hello World" =~ m{World};   # matches, note the matching '{}'
!     "/usr/bin/perl" =~ m"/perl"; # matches, '/' becomes ordinary char
! 
! C</World/>, C<m!World!>, and C<m{World}> all represent the
! same thing.  When, e.g., C<""> is used as a delimiter, the forward
! slash C<'/'> becomes an ordinary character and can be used in a regexp 
! without trouble.
! 
! Let's consider how different regexps would match C<"Hello World">:
  
      "Hello World" =~ /world/;  # doesn't match
      "Hello World" =~ /o W/;    # matches
***************
*** 113,126 ****
  
  The first regexp C<world> doesn't match because regexps are
  case-sensitive.  The second regexp matches because the substring
! S<C<'o W'> >
! occurs in the string S<C<"Hello World"> >.  The space character ' ' is
! treated like any other character in a regexp and is needed to match in
! this case.  The lack of a space character is the reason the third
! regexp C<'oW'> doesn't match.  The fourth regexp C<'World '> doesn't match
! because there is a space at the end of the regexp, but not at the end
! of the string.  The lesson here is that regexps must match a part of
! the string I<exactly> in order for the statement to be true.
  
  With respect to character matching, there are a few more points you
  need to know about.   First of all, not all characters can be used 'as
--- 127,146 ----
  
  The first regexp C<world> doesn't match because regexps are
  case-sensitive.  The second regexp matches because the substring
! S<C<'o W'> > occurs in the string S<C<"Hello World"> >.  The space
! character ' ' is treated like any other character in a regexp and is
! needed to match in this case.  The lack of a space character is the
! reason the third regexp C<'oW'> doesn't match.  The fourth regexp
! C<'World '> doesn't match because there is a space at the end of the
! regexp, but not at the end of the string.  The lesson here is that
! regexps must match a part of the string I<exactly> in order for the
! statement to be true.
! 
! If a regexp matches in more than one place in the string, perl will
! always match at the earliest possible point in the string:
! 
!     "Hello World" =~ /o/;       # matches 'o' in 'Hello'
!     "That hat is red" =~ /hat/; # matches 'hat' in 'That'
  
  With respect to character matching, there are a few more points you
  need to know about.   First of all, not all characters can be used 'as
***************
*** 137,161 ****
      "2+2=4" =~ /2\+2/;   # matches, \+ is treated like an ordinary +
      "The interval is [0,1)." =~ /[0,1)./     # is a syntax error!
      "The interval is [0,1)." =~ /\[0,1\)\./  # matches
  
- The forward slash C</>, because it is used to delimit the regexp, is
- also special.  C</> can be matched either by backslashing it, or by
- changing the matching operator:
- 
-     "/usr/local/bin/perl" =~ /\/usr\/local\/bin\/perl/;  # matches
-     "/usr/local/bin/perl" =~ m!/usr/local/bin/perl!;     # matches
- 
- The second version is gotten by rewriting the matching operator C<//>
- as C<m!!>.  When this is done, C</> becomes an ordinary character and
- C<!> becomes the special delimiting character.  With an C<m> out front,
- any characters or matching delimiters C<(){}[]> can be used to enclose
- the regexp: C</World/>, C<m!World!>, and C<m{World}> all represent the
- same thing.
  
! The backslash character C<\> itself is a metacharacter and needs to be
! backslashed:
  
!     "C:\WIN32" =~ /C:\\WIN/;   # matches
  
  In addition to the metacharacters, there are some ASCII characters
  which don't have printable character equivalents and are instead
--- 157,174 ----
      "2+2=4" =~ /2\+2/;   # matches, \+ is treated like an ordinary +
      "The interval is [0,1)." =~ /[0,1)./     # is a syntax error!
      "The interval is [0,1)." =~ /\[0,1\)\./  # matches
+     "/usr/bin/perl" =~ /\/usr\/local\/bin\/perl/;  # matches
+ 
+ In the last regexp, the forward slash C<'/'> is also backslashed,
+ because it is used to delimit the regexp.  This can lead to LTS
+ (leaning toothpick syndrome), however, and it is often more readable
+ to change delimiters.
  
  
! The backslash character C<'\'> is a metacharacter itself and needs to
! be backslashed:
  
!     'C:\WIN32' =~ /C:\\WIN/;   # matches
  
  In addition to the metacharacters, there are some ASCII characters
  which don't have printable character equivalents and are instead
***************
*** 224,234 ****
  specify I<where> in the string the regexp should try to match.  To do
  this, we would use the B<anchor> metacharacters C<^> and C<$>.  The
  anchor C<^> means match at the beginning of the string and the anchor
! C<$> means match at the end of the string.  Here is how they are used:
  
      "housekeeper" =~ /keeper/;    # matches
      "housekeeper" =~ /^keeper/;   # doesn't match
      "housekeeper" =~ /keeper$/;   # matches
  
  The second regexp doesn't match because C<^> constrains C<keeper> to
  match only at the beginning of the string, but C<"housekeeper"> has
--- 237,249 ----
  specify I<where> in the string the regexp should try to match.  To do
  this, we would use the B<anchor> metacharacters C<^> and C<$>.  The
  anchor C<^> means match at the beginning of the string and the anchor
! C<$> means match at the end of the string, or before a newline at the
! end of the string.  Here is how they are used:
  
      "housekeeper" =~ /keeper/;    # matches
      "housekeeper" =~ /^keeper/;   # doesn't match
      "housekeeper" =~ /keeper$/;   # matches
+     "housekeeper\n" =~ /keeper$/; # matches
  
  The second regexp doesn't match because C<^> constrains C<keeper> to
  match only at the beginning of the string, but C<"housekeeper"> has
***************
*** 282,296 ****
      /cat/;       # matches 'cat'
      /[bcr]at/;   # matches 'bat, 'cat', or 'rat'
      /item[0123456789]/;  # matches 'item0' or ... or 'item9'
      /[yY][eE][sS]/;      # match 'yes' in a case-insensitive way
                           # 'yes', 'Yes', 'YES', etc.
  
! The last regexp displays a common task: perform a a case-insensitive
  match.  Perl provides away of avoiding all those brackets by simply
! appending an 'i' to the end of the match.  Then C</[yY][eE][sS]/;> can
! be rewritten as C</yes/i;>.  The 'i' stands for case-insensitive and is
! an example of a B<modifier> of the matching operation.  We will meet
! other modifiers later in the tutorial.
  
  We saw in the section above that there were ordinary characters, which
  represented themselves, and special characters, which needed a
--- 297,317 ----
      /cat/;       # matches 'cat'
      /[bcr]at/;   # matches 'bat, 'cat', or 'rat'
      /item[0123456789]/;  # matches 'item0' or ... or 'item9'
+     "abc" =~ /[cab/;     # matches 'a'
+ 
+ In the last statement, even though C<'c'> is the first character in
+ the class, C<'a'> matches because the first character position in the
+ string is the earliest point at which the regexp can match.
+ 
      /[yY][eE][sS]/;      # match 'yes' in a case-insensitive way
                           # 'yes', 'Yes', 'YES', etc.
  
! This regexp displays a common task: perform a a case-insensitive
  match.  Perl provides away of avoiding all those brackets by simply
! appending an C<'i'> to the end of the match.  Then C</[yY][eE][sS]/;>
! can be rewritten as C</yes/i;>.  The C<'i'> stands for
! case-insensitive and is an example of a B<modifier> of the matching
! operation.  We will meet other modifiers later in the tutorial.
  
  We saw in the section above that there were ordinary characters, which
  represented themselves, and special characters, which needed a
***************
*** 322,330 ****
      /item[0-9]/;  # matches 'item0' or ... or 'item9'
      /[0-9bx-z]aa/;  # matches '0aa', ..., '9aa',
                      # 'baa', 'xaa', 'yaa', or 'zaa'
!     /[0-9af-A-F]/;  # matches a hexadecimal digit
      /[0-9a-zA-Z_]/; # matches an alphanumeric character,
!                     # like those in a perl variable
  
  If C<'-'> is the first or last character in a character class, it is
  treated as an ordinary character; C<[-ab]>, C<[ab-]> and C<[a\-b]> are
--- 343,351 ----
      /item[0-9]/;  # matches 'item0' or ... or 'item9'
      /[0-9bx-z]aa/;  # matches '0aa', ..., '9aa',
                      # 'baa', 'xaa', 'yaa', or 'zaa'
!     /[0-9a-fA-F]/;  # matches a hexadecimal digit
      /[0-9a-zA-Z_]/; # matches an alphanumeric character,
!                     # like those in a perl variable name
  
  If C<'-'> is the first or last character in a character class, it is
  treated as an ordinary character; C<[-ab]>, C<[ab-]> and C<[a\-b]> are
***************
*** 332,341 ****
  
  The special character C<^> in the first position of a character class
  denotes a B<negated character class>, which matches any character but
! those in the bracket.  Then
  
!     /[^a]at/;  # doesn't match 'aat', but matches all other
!                # 'bat', 'cat, '0at', '%at', etc.
      /[^0-9]/;  # matches a non-numeric character
      /[a^]at/;  # matches 'aat' or '^at'; here '^' is ordinary
  
--- 353,363 ----
  
  The special character C<^> in the first position of a character class
  denotes a B<negated character class>, which matches any character but
! those in the bracket.  Both C<[...]> and C<[^...]> must match a
! character, or the match fails.  Then
  
!     /[^a]at/;  # doesn't match 'aat' or 'at', but matches
!                # all other 'bat', 'cat, '0at', '%at', etc.
      /[^0-9]/;  # matches a non-numeric character
      /[a^]at/;  # matches 'aat' or '^at'; here '^' is ordinary
  
***************
*** 364,370 ****
  \W is a negated \w; it represents any non-word character [^\w]
  
  =item *
! '.' matches any character but "\n"
  
  =back
  
--- 386,392 ----
  \W is a negated \w; it represents any non-word character [^\w]
  
  =item *
! The period '.' matches any character but "\n"
  
  =back
  
***************
*** 377,385 ****
                        # non-word char, followed by a word char
      /..rt/;           # matches any two chars, followed by 'rt'
      /end\./;          # matches 'end.'
  
! Because a period is a metacharacter, it needs to be escaped to
! match as an ordinary period.
  
  An anchor useful in basic regexps is the S<B<word anchor> >
  C<\b>.  This matches a boundary between a word character and a non-word
--- 399,411 ----
                        # non-word char, followed by a word char
      /..rt/;           # matches any two chars, followed by 'rt'
      /end\./;          # matches 'end.'
+     /end[.]/;         # same thing, matches 'end.'
  
! Because a period is a metacharacter, it needs to be escaped to match
! as an ordinary period. Because, for example, C<\d> and C<\w> are sets
! of characters, it is incorrect to think of C<[^\d\w]> as C<[\D\W]>; in
! fact C<[^\d\w]> is the same as C<[^\w]>, which is the same as
! C<[\W]>. Think DeMorgan's laws.
  
  An anchor useful in basic regexps is the S<B<word anchor> >
  C<\b>.  This matches a boundary between a word character and a non-word
***************
*** 400,406 ****
  while the string C<"\n"> represents one line, we would like to think
  of as empty.  Then
  
-     ""   =~ //;      # matches automatically
      ""   =~ /^$/;    # matches
      "\n" =~ /^$/;    # matches, "\n" is ignored
  
--- 426,431 ----
***************
*** 427,439 ****
  
  =item *
  no modifiers (//): Default behavior.  C<'.'> matches any character
! except C<"\n">.  C<^> and C<$> match I<only> at the start or the end of
! the string.
  
  =item *
  s modifier (//s): Treat string as a single long line.  C<'.'> matches
! any character, even C<"\n">.  C<^> and C<$> are able to match I<only>
! at the start or the end of the string.
  
  =item *
  m modifier (//m): Treat string as a set of multiple lines.  C<'.'>
--- 452,465 ----
  
  =item *
  no modifiers (//): Default behavior.  C<'.'> matches any character
! except C<"\n">.  C<^> matches only at the beginning of the string and
! C<$> matches only at the end or before a newline at the end.
  
  =item *
  s modifier (//s): Treat string as a single long line.  C<'.'> matches
! any character, even C<"\n">.  C<^> matches only at the beginning of
! the string and C<$> matches only at the end or before a newline at the
! end.
  
  =item *
  m modifier (//m): Treat string as a set of multiple lines.  C<'.'>
***************
*** 464,476 ****
  
  Most of the time, the default behavior is what is want, but C<//s> and
  C<//m> are occasionally very useful.  If C<//m> is being used, the start
! and the end of string can still be matched with the anchors C<\A> and
! C<\Z>:
  
      $x =~ /^Who/m;   # matches, "Who" at start of second line
      $x =~ /\AWho/m;  # doesn't match, "Who" is not at start of string
      $x =~ /girl$/m;  # matches, "girl" at end of first line
!     $x =~ /girl$/m;  # doesn't match, "girl" is not at end of string
  
  We now know how to create choices among classes of characters in a
  regexp.  What about choices among words or character strings? Such
--- 490,507 ----
  
  Most of the time, the default behavior is what is want, but C<//s> and
  C<//m> are occasionally very useful.  If C<//m> is being used, the start
! of the string can still be matched with C<\A> and the end of string
! can still be matched with the anchors C<\Z> (matches both the end and
! the newline before, like C<$>), and C<\z> (matches only the end):
  
      $x =~ /^Who/m;   # matches, "Who" at start of second line
      $x =~ /\AWho/m;  # doesn't match, "Who" is not at start of string
+ 
      $x =~ /girl$/m;  # matches, "girl" at end of first line
!     $x =~ /girl\Z/m; # doesn't match, "girl" is not at end of string
! 
!     $x =~ /Perl\Z/m; # matches, "Perl" is at newline before end
!     $x =~ /Perl\z/m; # doesn't match, "Perl" is not at end of string
  
  We now know how to create choices among classes of characters in a
  regexp.  What about choices among words or character strings? Such
***************
*** 479,508 ****
  =head2 Matching this or that
  
  Sometimes we would like to our regexp to be able to match different
! possible words or character strings.  This is accomplished by using the
! B<alternation> metacharacter C<|>.  To match C<dog> or C<cat>, we form
! the regexp C<dog|cat>.  With this regexp, perl will first try to match
! the the first alternative, C<dog>.  If C<dog> doesn't match, perl will
! then try the next alternative, C<cat>.  If C<cat> doesn't match either,
! then the match fails.  Some examples:
! 
!     "cats and dogs" =~ /dog|cat|bird/;  # matches "dog"
      "cats and dogs" =~ /cat|dog|bird/;  # matches "cat"
!     "birddog"       =~ /cat|dog|bird/;  # matches "dog"
!     "catbird"       =~ /cat|dog|bird/;  # matches "cat"
!     "jaybird"       =~ /cat|dog|bird/;  # matches "bird"
      "cats"          =~ /c|ca|cat|cats/; # matches "c"
      "cats"          =~ /cats|cat|ca|c/; # matches "cats"
-     "cab"           =~ /a|b|c/          # matches "a"
-                                         # /a|b|c/ == /[abc]/
  
! The second and third to last examples show the importance of
! alternative order.  When one alternative is a subset of the other, try
! to match the longer one first.   The last example points out that
! character classes are like alternations of characters.  In general, the
! first alternative that allows the regexp match to succeed wil be the
! one that matches.  Sometimes this is stated as "perl always matches the
! leftmost possible alternative".
  
  =head2 Grouping things and hierarchical matching
  
--- 510,546 ----
  =head2 Matching this or that
  
  Sometimes we would like to our regexp to be able to match different
! possible words or character strings.  This is accomplished by using
! the B<alternation> metacharacter C<|>.  To match C<dog> or C<cat>, we
! form the regexp C<dog|cat>.  As before, perl will try to match the
! regexp at the earliest possible point in the string.  At each
! character position, perl will first try to match the first
! alternative, C<dog>.  If C<dog> doesn't match, perl will then try the
! next alternative, C<cat>.  If C<cat> doesn't match either, then the
! match fails and perl moves to the next position in the string.  Some
! examples:
!  
      "cats and dogs" =~ /cat|dog|bird/;  # matches "cat"
!     "cats and dogs" =~ /dog|cat|bird/;  # matches "cat"
! 
! Even though C<dog> is the first alternative in the second regexp,
! C<cat> is able to match earlier in the string.
! 
      "cats"          =~ /c|ca|cat|cats/; # matches "c"
      "cats"          =~ /cats|cat|ca|c/; # matches "cats"
  
! Here, all the alternatives match at the first string position, so the
! first alternative is the one that matches.  If some of the
! alternatives are truncations of the others, put the longest ones first
! to give them a chance to match.
! 
!     "cab" =~ /a|b|c/ # matches "c" 
!                      # /a|b|c/ == /[abc]/ 
! 
! The last example points out that character classes are like
! alternations of characters.  At a given character position, the first
! alternative that allows the regexp match to succeed wil be the one
! that matches.
  
  =head2 Grouping things and hierarchical matching
  
***************
*** 536,561 ****
      "20" =~ /(19|20|)\d\d/;  # matches the null alternative '()\d\d',
                               # because '20\d\d' can't match
  
! Alternations behave the same way in groups as out of them: the
! leftmost alternative that allows the regexp to match is taken.  So in
! the last example, C<"20"> matches the second alternative, but there is
! nothing left over to match the next two digits C<\d\d>.  So perl moves
! on to the next alternative, which is the null alternative and that
! works, since C<"20"> is two digits.
  
  The process of trying one alternative, seeing if it matches, and
  moving on to the next alternative if it doesn't, is called
  B<backtracking>.  The term 'backtracking' comes from the idea that
  matching a regexp is like a walk in the woods.  Successfully matching
! a regexp is like arriving at a destination.  In both cases there may be
! many paths, some of which get you there, and some which are dead
! ends.  When you walk along a trail and hit a dead end, you have to
! backtrack along the trail to an earlier point to try another trail.  If
! you hit your destination, you stop immediately and forget about
! trying all the other trails.  You are persistent, and only if you have
! tried all the trails and not arrived at your destination, do you
! declare failure.  To be concrete, here is a step-by-step analysis of
! what perl does when it tries to match the regexp
  
      "abcde" =~ /(abd|abc)(df|d|de)/;
  
--- 574,602 ----
      "20" =~ /(19|20|)\d\d/;  # matches the null alternative '()\d\d',
                               # because '20\d\d' can't match
  
! Alternations behave the same way in groups as out of them: at a given
! string position, the leftmost alternative that allows the regexp to
! match is taken.  So in the last example at tth first string position,
! C<"20"> matches the second alternative, but there is nothing left over
! to match the next two digits C<\d\d>.  So perl moves on to the next
! alternative, which is the null alternative and that works, since
! C<"20"> is two digits.
  
  The process of trying one alternative, seeing if it matches, and
  moving on to the next alternative if it doesn't, is called
  B<backtracking>.  The term 'backtracking' comes from the idea that
  matching a regexp is like a walk in the woods.  Successfully matching
! a regexp is like arriving at a destination.  There are many possible
! trailheads, one for each string position, and each one is tried in
! order, left to right.  From each trailhead there may be many paths,
! some of which get you there, and some which are dead ends.  When you
! walk along a trail and hit a dead end, you have to backtrack along the
! trail to an earlier point to try another trail.  If you hit your
! destination, you stop immediately and forget about trying all the
! other trails.  You are persistent, and only if you have tried all the
! trails from all the trailheads and not arrived at your destination, do
! you declare failure.  To be concrete, here is a step-by-step analysis
! of what perl does when it tries to match the regexp
  
      "abcde" =~ /(abd|abc)(df|d|de)/;
  
***************
*** 563,578 ****
  
  =item 0 Start with the first letter in the string 'a'.
  
! =item 1 Pick the first alternative in the first group 'abd'.
  
  =item 2 Match 'a' followed by 'b'. So far so good.
  
  =item 3 'd' in the regexp doesn't match 'c' in the string - a dead
! end.  So backtrack three characters and pick the second alternative in
  the first group 'abc'.
  
  =item 4 Match 'a' followed by 'b' followed by 'c'.  We are on a roll
! and have satisfied the first group.
  
  =item 5 Move on to the second group and pick the first alternative
  'df'.
--- 604,619 ----
  
  =item 0 Start with the first letter in the string 'a'.
  
! =item 1 Try the first alternative in the first group 'abd'.
  
  =item 2 Match 'a' followed by 'b'. So far so good.
  
  =item 3 'd' in the regexp doesn't match 'c' in the string - a dead
! end.  So backtrack two characters and pick the second alternative in
  the first group 'abc'.
  
  =item 4 Match 'a' followed by 'b' followed by 'c'.  We are on a roll
! and have satisfied the first group. Set $1 to 'abc'.
  
  =item 5 Move on to the second group and pick the first alternative
  'df'.
***************
*** 580,589 ****
  =item 6 Match the 'd'.
  
  =item 7 'f' in the regexp doesn't match 'e' in the string, so a dead
! end.  Backtrack two characters and pick the second alternative in the
  second group 'd'.
  
! =item 8 'd' matches.
  
  =item 9 We are at the end of the regexp, so we are done! We have
  matched 'abcd' out of the string "abcde".
--- 621,631 ----
  =item 6 Match the 'd'.
  
  =item 7 'f' in the regexp doesn't match 'e' in the string, so a dead
! end.  Backtrack one character and pick the second alternative in the
  second group 'd'.
  
! =item 8 'd' matches. The second grouping is satisfied, so set $2 to
! 'd'. 
  
  =item 9 We are at the end of the regexp, so we are done! We have
  matched 'abcd' out of the string "abcde".
***************
*** 592,604 ****
  
  There are a couple of things to note about this analysis.  First, the
  third alternative in the second group 'de' also allows a match, but we
! stopped before we got to it - leftmost always wins.  Second, we were
! able to get a match at the first character position of the string
! 'a'.  If there were no matches at the first position, perl would move
! to the second character position 'b' and attempt the match all over
! again.  Only when all possible paths at all possible character
! positions have been exhausted does perl give give up and declare
! S<C<"abcde" =~ /(abd|abc)(df|d|de)/;> > to be false.
  
  Even with all this work, regexp matching happens remarkably fast.  To
  speed things up, during compilation stage, perl compiles the regexp
--- 634,646 ----
  
  There are a couple of things to note about this analysis.  First, the
  third alternative in the second group 'de' also allows a match, but we
! stopped before we got to it - at a given character position, leftmost
! wins.  Second, we were able to get a match at the first character
! position of the string 'a'.  If there were no matches at the first
! position, perl would move to the second character position 'b' and
! attempt the match all over again.  Only when all possible paths at all
! possible character positions have been exhausted does perl give give
! up and declare S<C<$string =~ /(abd|abc)(df|d|de)/;> > to be false.
  
  Even with all this work, regexp matching happens remarkably fast.  To
  speed things up, during compilation stage, perl compiles the regexp
***************
*** 669,674 ****
--- 711,735 ----
  and backreferences C<\1>, C<\2>, ... only inside a regexp; not doing
  so may lead to surprising and/or undefined results.
  
+ In addition to what was matched, Perl 5.6.0 also provides the
+ positions of what was matched with the C<@-> and C<@+>
+ arrays. C<$-[0]> is the position of the start of the entire match and
+ C<$+[0]> is the position of the end. Similarly, C<$-[n]> is the
+ position of the start of the C<$n> match and C<$+[n]> is the position
+ of the end. If C<$n> is undefined, so are C<$-[n]> and C<$+[n]>. Then
+ this code
+ 
+     $x = "Mmm...donut, thought Homer";
+     $x =~ /^(Mmm|Yech)\.\.\.(donut|peas)/; # matches
+     foreach $expr (1..$#-) {
+         print "Match $expr: '${$expr}' at position ($-[$expr],$+[$expr])\n";
+     }
+ 
+ prints
+ 
+     Match 1: 'Mmm' at position (0,3)
+     Match 2: 'donut' at position (6,11)
+ 
  Even if there are no groupings in a regexp, it is still possible to
  find out what exactly matched in a string.  If you use them, perl
  will set C<$`> to the part of the string before the match, will set C<$&>
***************
*** 681,690 ****
  
  In the second match, S<C<$` = ''> > because the regexp matched at the
  first character position in the string and stopped, it never saw the
! second 'the'.  It is important to note that using C<$`> and C<$'> slows
! down regexp matching quite a bit, and C<$&> slows it down to a lesser
! extent.  So if raw performance is a goal of your application, they
! should be avoided.
  
  =head2 Matching repetitions
  
--- 742,757 ----
  
  In the second match, S<C<$` = ''> > because the regexp matched at the
  first character position in the string and stopped, it never saw the
! second 'the'.  It is important to note that using C<$`> and C<$'>
! slows down regexp matching quite a bit, and C<$&> slows it down to a
! lesser extent, because if they are used in one regexp in a program,
! they are generated for <all> regexps in the program.  So if raw
! performance is a goal of your application, they should be avoided.
! If you need them, use C<@-> and C<@+> instead:
! 
!     $` is the same as substr( $x, 0, $-[0] )
!     $& is the same as substr( $x, $-[0], $+[0]-$-[0] )
!     $' is the same as substr( $x, $+[0] )
  
  =head2 Matching repetitions
  
***************
*** 761,767 ****
  One might initially guess that perl would find the C<at> in C<cat> and
  stop there, but that wouldn't give the longest possible string to the
  first quantifier C<.*>.  Instead, the first quantifier C<.*> grabs as
! much of the string as possible which still having the regexp match.  In
  this example, that means having the C<at> sequence with the final <at>
  in the string.  The other important principle illustrated here is that
  when there are two or more elements in a regexp, the I<leftmost>
--- 828,834 ----
  One might initially guess that perl would find the C<at> in C<cat> and
  stop there, but that wouldn't give the longest possible string to the
  first quantifier C<.*>.  Instead, the first quantifier C<.*> grabs as
! much of the string as possible while still having the regexp match.  In
  this example, that means having the C<at> sequence with the final <at>
  in the string.  The other important principle illustrated here is that
  when there are two or more elements in a regexp, the I<leftmost>
***************
*** 790,806 ****
  C<{n,m}> will in general match as much of the string as possible while
  still allowing the whole regexp to match.
  
! =item *
  Principle 3: If there are two or more elements in a regexp, the
! leftmost quantifier, if any, will match as much of the string as
! possible while still allowing the whole regexp to match.  The next
! leftmost quantifier, if any, will try to match as much of the string
! remaining available to it as possible, while still allowing the whole
! regexp to match.  And so on, until all the regexp elements are
  satisfied.
  
  =back
  
  Here is an example of these principles in action:
  
      $x = "The programming republic of Perl";
--- 857,878 ----
  C<{n,m}> will in general match as much of the string as possible while
  still allowing the whole regexp to match.
  
! =item * 
  Principle 3: If there are two or more elements in a regexp, the
! leftmost greedy quantifier, if any, will match as much of the string
! as possible while still allowing the whole regexp to match.  The next
! leftmost greedy quantifier, if any, will try to match as much of the
! string remaining available to it as possible, while still allowing the
! whole regexp to match.  And so on, until all the regexp elements are
  satisfied.
  
  =back
  
+ As we have seen above, Principle 0 overrides the others - the regexp
+ will be matched as early as possible, with the other principles
+ determining how the regexp matches at that earliest character
+ position.
+ 
  Here is an example of these principles in action:
  
      $x = "The programming republic of Perl";
***************
*** 809,835 ****
                                # $2 = 'r'
                                # $3 = 'l'
  
! Here you might think that C<e>, being leftmost in the alternation,
! would be matched, but C<r> produces the longest string in the first
! quantifier.
  
      $x =~ /(m{1,2})(.*)$/;  # matches,
                              # $1 = 'mm'
                              # $2 = 'ing republic of Perl'
      $x =~ /.*(m{1,2})(.*)$/;  # matches,
                                # $1 = 'm'
                                # $2 = 'ing republic of Perl'
      $x =~ /(.?)(m{1,2})(.*)$/;  # matches,
                                  # $1 = 'a'
                                  # $2 = 'mm'
                                  # $3 = 'ing republic of Perl'
  
! In the first regexp, C<m{1,2}> is the first quantifier so it gets to
! match a maximal C<mm>.  In the second regexp, the first quantifier C.*>
! grabs as much as possible, leaving just a single C<m> for the second
! quantifier C<m{1,2}>.  In the third regexp, C<.?> eats its maximal one
! character at the earliest possible position in the string, C<a>,
! leaving C<m{1,2}> the opportunity to match both C<m>'s.
  
  Sometimes greed is not good.  At times, we would like quantifiers to
  match a I<minimal> piece of string, rather than a maximal piece.  For
--- 881,920 ----
                                # $2 = 'r'
                                # $3 = 'l'
  
! This regexp matches at the earliest string position, C<'T'>.  One
! might think that C<e>, being leftmost in the alternation, would be
! matched, but C<r> produces the longest string in the first quantifier.
  
      $x =~ /(m{1,2})(.*)$/;  # matches,
                              # $1 = 'mm'
                              # $2 = 'ing republic of Perl'
+ 
+ Here, The earliest possible match is at the first C<'m'> in
+ C<programming>. C<m{1,2}> is the first quantifier, so it gets to match
+ a maximal C<mm>.
+ 
      $x =~ /.*(m{1,2})(.*)$/;  # matches,
                                # $1 = 'm'
                                # $2 = 'ing republic of Perl'
+ 
+ Here, the regexp matches at the start of the string. The first
+ quantifier C<.*> grabs as much as possible, leaving just a single
+ C<'m'> for the second quantifier C<m{1,2}>.
+ 
      $x =~ /(.?)(m{1,2})(.*)$/;  # matches,
                                  # $1 = 'a'
                                  # $2 = 'mm'
                                  # $3 = 'ing republic of Perl'
  
! Here, C<.?> eats its maximal one character at the earliest possible
! position in the string, C<'a'> in C<programming>, leaving C<m{1,2}>
! the opportunity to match both C<m>'s. Finally, 
! 
!     "aXXXb" =~ /(X*)/; # matches with $1 = ''
! 
! because it can match zero copies of C<'X'> at the beginning of the
! string.  If you definitely want to match at least one C<'X'>, use
! C<X+>, not C<X*>.
  
  Sometimes greed is not good.  At times, we would like quantifiers to
  match a I<minimal> piece of string, rather than a maximal piece.  For
***************
*** 868,886 ****
                                # $2 = 'e'
                                # $3 = ' programming republic of Perl'
  
! The first quantifier C<.+?> is minimal and the minimal string that
! will allow the alternation to match is C<Th>, with the alternation
! C<e|r> matching C<e>.  The second quantifier C<.*> is free to gobble up
! the rest of the string.
  
      $x =~ /(m{1,2}?)(.*?)$/;  # matches,
                                # $1 = 'm'
                                # $2 = 'ming republic of Perl'
  
! In this regexp, the minimal C<m{1,2}?> matches just one
! C<m>.  Although the second quantifier C<.*?> would prefer to match no
! characters, it is constrained by the end-of-string anchor C<$> to
! match the rest of the string.
  
      $x =~ /(.*?)(m{1,2}?)(.*)$/;  # matches,
                                    # $1 = 'The progra'
--- 953,972 ----
                                # $2 = 'e'
                                # $3 = ' programming republic of Perl'
  
! The minimal string that will allow both the start of the string C<^>
! and the alternation to match is C<Th>, with the alternation C<e|r>
! matching C<e>.  The second quantifier C<.*> is free to gobble up the
! rest of the string.
  
      $x =~ /(m{1,2}?)(.*?)$/;  # matches,
                                # $1 = 'm'
                                # $2 = 'ming republic of Perl'
  
! The first string position that this regexp can match is at the first
! C<'m'> in C<programming>. At this position, the minimal C<m{1,2}?>
! matches just one C<'m'>.  Although the second quantifier C<.*?> would
! prefer to match no characters, it is constrained by the end-of-string
! anchor C<$> to match the rest of the string.
  
      $x =~ /(.*?)(m{1,2}?)(.*)$/;  # matches,
                                    # $1 = 'The progra'
***************
*** 901,909 ****
                                   # $2 = 'mm'
                                   # $3 = 'ing republic of Perl'
  
! Just as in the previous regexp, the first quantifier C<.??> must match
! at position C<a>, so it does.  The second quantifier is greedy, so it
! matches C<mm>, and the third matches the rest of the string.
  
  Just like alternation, quantifiers are also susceptible to
  backtracking.  Here is a step-by-step analysis of the example
--- 987,1012 ----
                                   # $2 = 'mm'
                                   # $3 = 'ing republic of Perl'
  
! Just as in the previous regexp, the first quantifier C<.??> can match
! earliest at position C<'a'>, so it does.  The second quantifier is
! greedy, so it matches C<mm>, and the third matches the rest of the
! string.
! 
! We can modify principle 3 above to take into account non-greedy
! quantifiers: 
! 
! =over 4
! 
! =item * 
! Principle 3: If there are two or more elements in a regexp, the
! leftmost greedy (non-greedy) quantifier, if any, will match as much
! (little) of the string as possible while still allowing the whole
! regexp to match.  The next leftmost greedy (non-greedy) quantifier, if
! any, will try to match as much (little) of the string remaining
! available to it as possible, while still allowing the whole regexp to
! match.  And so on, until all the regexp elements are satisfied.
! 
! =back
  
  Just like alternation, quantifiers are also susceptible to
  backtracking.  Here is a step-by-step analysis of the example
***************
*** 948,959 ****
  and C<*>: one repetition with C<b+> of length n, two repetitions with
  the first C<b+> length k and the second with length n-k, m repetitions
  whose bits add up to length n, etc.  In fact there are an exponential
! number of ways to partition a string as a function of length.  A regexp
! may get lucky and match early in the process, but if there is no
! match, perl will try I<every> possibility before giving up.  So be
! careful with nested C<*>'s and C<+>'s.  The book I<Mastering regular
! expressions> by Jeffrey Friedl gives a wonderful discussion of this and
! other efficiency issues.
  
  =head2 Building a regexp
  
--- 1051,1062 ----
  and C<*>: one repetition with C<b+> of length n, two repetitions with
  the first C<b+> length k and the second with length n-k, m repetitions
  whose bits add up to length n, etc.  In fact there are an exponential
! number of ways to partition a string as a function of length.  A
! regexp may get lucky and match early in the process, but if there is
! no match, perl will try I<every> possibility before giving up.  So be
! careful with nested C<*>'s, C<{n,m}>'s, and C<+>'s.  The book
! I<Mastering regular expressions> by Jeffrey Friedl gives a wonderful
! discussion of this and other efficiency issues.
  
  =head2 Building a regexp
  
***************
*** 1037,1047 ****
  
  If whitespace is mostly irrelevant, how does one include space
  characters in an extended regexp? The answer is to backslash it
- 
  S<C<'\ '> > or put it in a character class S<C<[ ]> >.  The same thing
! goes for pound signs, use C<\#> or C<[#]>.  For instance, Perl allows a
! space between the sign and the mantissa/integer, and we could add this
! to our regexp as follows:
  
     /^
        [+-]?\ *      # first, match an optional sign *and space*
--- 1140,1149 ----
  
  If whitespace is mostly irrelevant, how does one include space
  characters in an extended regexp? The answer is to backslash it
  S<C<'\ '> > or put it in a character class S<C<[ ]> >.  The same thing
! goes for pound signs, use C<\#> or C<[#]>.  For instance, Perl allows
! a space between the sign and the mantissa/integer, and we could add
! this to our regexp as follows:
  
     /^
        [+-]?\ *      # first, match an optional sign *and space*
***************
*** 1146,1158 ****
      "dog" =~ /d/;  # 'd' matches
      "dogbert =~ //;  # this matches the 'd' regexp used before
  
! The final two modifiers C<//g> and C<//c> concern multiple
! matches.  The modifier C<//g> stands for global matching and allows the
! the matching operator to match within a string as many times as
! possible.  In scalar context, successive invocations of against a
! string will C<//g> jump from match to match, keeping track of position
! in the string as it goes along.  You can get or set the position with
! the C<pos()> function.
  
  The use of C<//g> is shown in the following example.  Suppose we have
  a string that consists of words separated by spaces.  If we know how
--- 1248,1260 ----
      "dog" =~ /d/;  # 'd' matches
      "dogbert =~ //;  # this matches the 'd' regexp used before
  
! The final two modifiers C<//g> and C<//c> concern multiple matches.
! The modifier C<//g> stands for global matching and allows the the
! matching operator to match within a string as many times as possible.
! In scalar context, successive invocations against a string will have
! `C<//g> jump from match to match, keeping track of position in the
! string as it goes along.  You can get or set the position with the
! C<pos()> function.
  
  The use of C<//g> is shown in the following example.  Suppose we have
  a string that consists of words separated by spaces.  If we know how
***************
*** 1202,1208 ****
      $metric = 1;  # use metric units
      ...
      $x = <FILE>;  # read in measurement
!     $x =~ /^([+-]?\d+)\s*/;  # get magnitude
      $weight = $1;
      if ($metric) { # error checking
          print "Units error!" unless $x =~ /\Gkg\./g;
--- 1304,1310 ----
      $metric = 1;  # use metric units
      ...
      $x = <FILE>;  # read in measurement
!     $x =~ /^([+-]?\d+)\s*/g;  # get magnitude
      $weight = $1;
      if ($metric) { # error checking
          print "Units error!" unless $x =~ /\Gkg\./g;
***************
*** 1210,1216 ****
      else {
          print "Units error!" unless $x =~ /\Glbs\./g;
      }
!     $x =~ /\G\s+(widget|sprocket)/;  # continue processing
  
  The combination of C<//g> and C<\G> allows us to process the string a
  bit at a time and use arbitrary Perl logic to decide what to do next.
--- 1312,1318 ----
      else {
          print "Units error!" unless $x =~ /\Glbs\./g;
      }
!     $x =~ /\G\s+(widget|sprocket)/g;  # continue processing
  
  The combination of C<//g> and C<\G> allows us to process the string a
  bit at a time and use arbitrary Perl logic to decide what to do next.
***************
*** 1259,1275 ****
  important not only to match what is desired, but to reject what is not
  desired.
  
  Regular expressions also play a big role in B<search and replace>
  operations in Perl.  Search and replace is accomplished with the
  C<s///> operator.  The general form is
  C<s/regexp/replacement/modifiers>, with everything we know about
  regexps and modifiers applying in this case as well.  The
! C<replacement> is a Perl expression that replaces in the string
! whatever is matched with the C<regexp>.  The operator C<=~> is also
! used here to associate a string with C<s///>.  If matching against
! C<$_>, the S<C<$_ =~> > can be dropped.  If there is a match, C<s///>
! returns the number of substitutions made, otherwise it returns false.
! Here are a few examples:
  
      $x = "Time to feed the cat!";
      $x =~ s/cat/hacker/;   # $x contains "Time to feed the hacker!"
--- 1361,1379 ----
  important not only to match what is desired, but to reject what is not
  desired.
  
+ B<search and replace>
+ 
  Regular expressions also play a big role in B<search and replace>
  operations in Perl.  Search and replace is accomplished with the
  C<s///> operator.  The general form is
  C<s/regexp/replacement/modifiers>, with everything we know about
  regexps and modifiers applying in this case as well.  The
! C<replacement> is a Perl double quoted string that replaces in the
! string whatever is matched with the C<regexp>.  The operator C<=~> is
! also used here to associate a string with C<s///>.  If matching
! against C<$_>, the S<C<$_ =~> > can be dropped.  If there is a match,
! C<s///> returns the number of substitutions made, otherwise it returns
! false.  Here are a few examples:
  
      $x = "Time to feed the cat!";
      $x =~ s/cat/hacker/;   # $x contains "Time to feed the hacker!"
***************
*** 1302,1308 ****
      $regexp = shift;
      $replacement = shift;
      while (<>) {
!         print if s/$regexp/$replacement/go;
      }
      ^D
  
--- 1406,1413 ----
      $regexp = shift;
      $replacement = shift;
      while (<>) {
!         s/$regexp/$replacement/go;
!         print;
      }
      ^D
  
***************
*** 1315,1321 ****
  
  A modifier available specifically to search and replace is the
  C<s///e> evaluation modifier.  C<s///e> wraps an C<eval{...}> around
! the replacement expression and the result is substituted for the
  matched substring.  C<s///e> is useful if you need to do a bit of
  computation in the process of replacing text.  This example counts
  character frequencies in a line:
--- 1420,1426 ----
  
  A modifier available specifically to search and replace is the
  C<s///e> evaluation modifier.  C<s///e> wraps an C<eval{...}> around
! the replacement string and the evaluated result is substituted for the
  matched substring.  C<s///e> is useful if you need to do a bit of
  computation in the process of replacing text.  This example counts
  character frequencies in a line:
***************
*** 1344,1349 ****
--- 1449,1456 ----
  returns the same thing as in scalar context, i.e., the number of
  matches.
  
+ B<The split operator>
+ 
  The B<C<split> > function can also optionally use a matching operator
  C<m//> to split a string.  C<split /regexp/, string, limit> splits
  C<string> into a list of substrings and returns that list.  The regexp
***************
*** 1357,1363 ****
                                 # $word[1] = 'and'
                                 # $word[2] = 'Hobbes'
  
! If the empty regexp C<//> is used, the the regexp always matches and
  the string is split into individual characters.  If the regexp has
  groupings, then list produced contains the matched substrings from the
  groupings as well.  For instance,
--- 1464,1470 ----
                                 # $word[1] = 'and'
                                 # $word[2] = 'Hobbes'
  
! If the empty regexp C<//> is used, the regexp always matches and
  the string is split into individual characters.  If the regexp has
  groupings, then list produced contains the matched substrings from the
  groupings as well.  For instance,
***************
*** 1421,1427 ****
      $x =~ /\Ukeypunch/;  # matches punch card string
  
  If there is no C<\E>, case is converted until the end of the
! string.
  
  Control characters can be escaped with C<\c>, so that a control-Z
  character would be matched with C<\cZ>.  The escape sequence
--- 1528,1536 ----
      $x =~ /\Ukeypunch/;  # matches punch card string
  
  If there is no C<\E>, case is converted until the end of the
! string. The regexps C<\L\u$word> or C<\u\L$word> convert the first
! character of C<$word> to uppercase and the rest of the characters to
! lowercase. 
  
  Control characters can be escaped with C<\c>, so that a control-Z
  character would be matched with C<\cZ>.  The escape sequence
***************
*** 1878,1903 ****
  matched, otherwise the C<no-regexp> will be matched.
  
  The C<condition> can have two forms.  The first form is simply an
! integer, with zero false and non-zero true.  The second form is a zero
! width assertion, either a lookahead, a lookbehind, or a code
! assertion (discussed in the next section).
! 
! The integer form of the C<condition> might seem a little boring at
! first, until one realizes that the integer may be interpolated from a
! variable.  This allows a dynamic update of the regexp as a function of
! the outside conditions.  For instance, in the units checking
! example above, a conditional expression allows us to rewrite:
! 
!     if ($metric) { # error checking
!         print "Units error!" unless $x =~ /\Gkg\./g;
!     }
!     else {
!         print "Units error!" unless $x =~ /\Glbs\./g;
!     }
  
! as
! 
!     print "Units error!" unless $x =~ /\G(?($metric)kg|lbs)\./g;
  
  The lookbehind C<condition> allows, along with backreferences,
  an earlier part of the match to influence a later part of the
--- 1987,2012 ----
  matched, otherwise the C<no-regexp> will be matched.
  
  The C<condition> can have two forms.  The first form is simply an
! integer in parentheses C<(integer)>.  It is true if the corresponding
! backreference C<\integer> matched earlier in the regexp.  The second
! form is a bare zero width assertion C<(?...)>, either a
! lookahead, a lookbehind, or a code assertion (discussed in the next
! section).
! 
! The integer form of the C<condition> allows us to choose, with more
! flexibility, what to match based on what matched earlier in the
! regexp. This searches for words of the form C<"$x$x"> or
! C<"$x$y$y$x">: 
  
!     % simple_grep '^(\w+)(\w+)?(?(2)\2\1|\1)$' /usr/dict/words
!     beriberi
!     coco
!     couscous
!     deed
!     ...
!     toot
!     toto
!     tutu
  
  The lookbehind C<condition> allows, along with backreferences,
  an earlier part of the match to influence a later part of the
***************
*** 2185,2190 ****
--- 2294,2327 ----
  n the compilation list above.  See
  L<perldebguts/"Debugging regular expressions"> for much more detail.
  
+ An alternative method of debugging regexps is to embed C<print>
+ statements within the regexp.  This provides a blow-by-blow account of
+ the backtracking in an alternation:
+ 
+     "that this" =~ m@(?{print "Start at position ", pos, "\n";})
+                      t(?{print "t1\n";})
+                      h(?{print "h1\n";})
+                      i(?{print "i1\n";})
+                      s(?{print "s1\n";})
+                          |
+                      t(?{print "t2\n";})
+                      h(?{print "h2\n";})
+                      a(?{print "a2\n";})
+                      t(?{print "t2\n";})
+                      (?{print "Done at position ", pos, "\n";})
+                     @x;
+ 
+ prints
+ 
+     Start at position 0
+     t1
+     h1
+     t2
+     h2
+     a2
+     t2
+     Done at position 4
+ 
  =head1 BUGS
  
  Code expressions, conditional expressions, and independent expressions
***************
*** 2203,2210 ****
  regular expressions, see the book I<Mastering Regular Expressions> by
  Jeffrey Friedl (published by O'Reilly, ISBN 1556592-257-3).
  
! Note: inspiration for the stop codon DNA example came from the ZIP
  code example in chapter 7 of I<Mastering Regular Expressions>.
  
! =cut
  
--- 2340,2361 ----
  regular expressions, see the book I<Mastering Regular Expressions> by
  Jeffrey Friedl (published by O'Reilly, ISBN 1556592-257-3).
  
! =head1 AUTHOR AND COPYRIGHT
! 
! Copyright (c) 2000 Mark Kvale 
! All rights reserved.
! 
! This document may be distributed under the same terms as Perl itself. 
! 
! =head2 Acknowledgments
! 
! The inspiration for the stop codon DNA example came from the ZIP
  code example in chapter 7 of I<Mastering Regular Expressions>.
  
! The author would like to thank 
! Jeff Pinyan,
! Peter Haworth,
! Ronald J Kimball,
! and Joe Smith for all their helpful comments.
  
+ =cut



nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About