[svn:perlfaq] r3702 - perlfaq/trunk

[email protected] Mon, 20 Mar 2006 22:08:27 -0800 (PST)
Newsgroups perl.cvs.perlfaq
Message-ID <[email protected]>
Author: comdog
Date: Mon Mar 20 22:08:26 2006
New Revision: 3702

Modified:
   perlfaq/trunk/perlfaq.pod
   perlfaq/trunk/perlfaq4.pod
   perlfaq/trunk/perlfaq6.pod

Log:
* perlfaq6.pod - replaced answer and changed the question:

-=head2 How do I match a pattern that is supplied by the user?
+=head2 How do I match a regular expression that's in a variable?

* perlfaq4: How do I find the day or week of the year?
	+ I took Time::Local out of the code, but forgot to take it
	out of the prose. I fixed that.



Modified: perlfaq/trunk/perlfaq.pod
==============================================================================
--- perlfaq/trunk/perlfaq.pod	(original)
+++ perlfaq/trunk/perlfaq.pod	Mon Mar 20 22:08:26 2006
@@ -1,6 +1,6 @@
 =head1 NAME
 
-perlfaq - frequently asked questions about Perl ($Revision$)
+perlfaq - frequently asked questions about Perl
 
 =head1 DESCRIPTION
 
@@ -24,8 +24,8 @@
 of the latest perlfaq to comp.lang.perl.misc.
 
 You can view the source tree at
-https://svn.perl.org/modules/perlfaq/trunk/ (which is outside of the
-main Perl source tree).  The SVN repository notes all changes to the FAQ
+http://cvs.perl.org/viewcvs/cvs-public/perlfaq/ (which is outside of the
+main Perl source tree).  The CVS repository notes all changes to the FAQ
 and holds the latest version of the working documents and may vary
 significantly from the version distributed with the latest version of
 Perl. Check the repository before sending your corrections.
@@ -171,7 +171,7 @@
 
 =item *
 
-How can I convince my sysadmin/supervisor/employees to use version 5/5.6.1/Perl instead of some other language?
+How can I convince others to use Perl?
 
 =back
 
@@ -735,7 +735,7 @@
 
 =item *
 
-How can I make a filehandle local to a subroutine?  How do I pass filehandles between subroutines?  How do I make an array of filehandles?
+How can I make a filehandle local to a subroutine?  How do I pass filehandles between subroutines?  How do I make an array of filehandles? 
 
 =item *
 
@@ -956,7 +956,7 @@
 
 =item *
 
-How do I match a pattern that is supplied by the user?
+How do I match a regular expression that's in a variable?
 
 =back
 

Modified: perlfaq/trunk/perlfaq4.pod
==============================================================================
--- perlfaq/trunk/perlfaq4.pod	(original)
+++ perlfaq/trunk/perlfaq4.pod	Mon Mar 20 22:08:26 2006
@@ -404,7 +404,7 @@
 	my $day_of_year  = strftime "%j", localtime;
 	my $week_of_year = strftime "%W", localtime;
 
-To get the day of year for any date, use the Time::Local module to get
+To get the day of year for any date, use C<POSIX>'s C<mktime> to get
 a time in epoch seconds for the argument to localtime.
 
 	use POSIX qw/mktime strftime/;

Modified: perlfaq/trunk/perlfaq6.pod
==============================================================================
--- perlfaq/trunk/perlfaq6.pod	(original)
+++ perlfaq/trunk/perlfaq6.pod	Mon Mar 20 22:08:26 2006
@@ -792,7 +792,7 @@
 
 =head2 How can I match strings with multibyte characters?
 X<regex, and multibyte characters> X<regexp, and multibyte characters>
-X<regular expression, and multibyte characters>
+X<regular expression, and multibyte characters> X<martian> X<encoding, Martian>
 
 Starting from Perl 5.6 Perl has had some level of multibyte character
 support.  Perl 5.8 or later is recommended.  Supported multibyte
@@ -861,31 +861,87 @@
 It does have the drawback of putting the wrong thing in $-[0] and $+[0],
 but this usually can be worked around.
 
-=head2 How do I match a pattern that is supplied by the user?
-
-Well, if it's really a pattern, then just use
-
-    chomp($pattern = <STDIN>);
-    if ($line =~ /$pattern/) { }
-
-Alternatively, since you have no guarantee that your user entered
-a valid regular expression, trap the exception this way:
-
-    if (eval { $line =~ /$pattern/ }) { }
-
-If all you really want is to search for a string, not a pattern,
-then you should either use the index() function, which is made for
-string searching, or, if you can't be disabused of using a pattern
-match on a non-pattern, then be sure to use C<\Q>...C<\E>, documented
-in L<perlre>.
-
-    $pattern = <STDIN>;
-
-    open (FILE, $input) or die "Couldn't open input $input: $!; aborting";
-    while (<FILE>) {
-	print if /\Q$pattern\E/;
-    }
-    close FILE;
+=head2 How do I match a regular expression that's in a variable?
+X<regex, in variable> X<eval> X<regex> X<quotemeta> X<\Q, regex>
+X<\E, regex>, X<qr//>
+
+(contributed by brian d foy)
+
+We don't have to hard-code patterns into the match operator (or
+anything else that works with regular expressions). We can put the
+pattern in a variable for later use.
+ 
+The match operator is a double quote context, so you can interpolate
+your variable just like a double quoted string. In this case, you
+read the regular expression as user input and store it in C<$regex>.
+Once you have the pattern in C<$regex>, you use that variable in the
+match operator.
+
+    chomp( my $regex = <STDIN> );
+    
+    if( $string =~ m/$regex/ ) { ... }
+
+Any regular expression special characters in C<$regex> are still 
+special, and the pattern still has to be valid or Perl will complain.
+For instance, in this pattern there is an unpaired parenthesis.
+
+	my $regex = "Unmatched ( paren";
+	
+	"Two parens to bind them all" =~ m/$regex/;
+	
+When Perl compiles the regular expression, it treats the parenthesis
+as the start of a memory match. When it doesn't find the closing
+parenthesis, it complains:
+
+	Unmatched ( in regex; marked by <-- HERE in m/Unmatched ( <-- HERE  paren/ at script line 3.                                                               
+
+You can get around this in several ways depending on our situation. 
+First, if you don't want any of the characters in the string to be
+special, you can escape them with C<quotemeta> before you use the string.
+
+    chomp( my $regex = <STDIN> );
+  	$regex = quotemeta( $regex );
+  	
+    if( $string =~ m/$regex/ ) { ... }
+
+You can also do this directly in the match operator using the C<\Q>
+and C<\E> sequences. The C<\Q> tells Perl where to start escaping
+special characters, and the C<\E> tells it where to stop (see L<perlop>
+for more details).
+
+    chomp( my $regex = <STDIN> );
+  	
+    if( $string =~ m/\Q$regex\E/ ) { ... }
+
+Alternately, you can use C<qr//>, the regular expression quote operator (see
+L<perlop> for more details).  It quotes and perhaps compiles the pattern, 
+and you can apply regular expression flags to the pattern.
+
+    chomp( my $input = <STDIN> );
+  	
+    my $regex = qr/$input/is;
+    
+    $string =~ m/$regex/  # same as m/$input/is; 
+
+You might also want to trap any errors by wrapping an C<eval> block
+around the whole thing.
+
+    chomp( my $input = <STDIN> );
+  	
+    eval { 
+    	if( $string =~ m/\Q$input\E/ ) { ... } 
+    	};
+    warn $@ if $@;
+    
+Or...
+
+	my $regex = eval { qr/$input/is };
+	if( defined $regex ) {
+		$string =~ m/$regex/;
+		}
+	else {
+		warn $@;
+		}
 
 =head1 REVISION