P e r l d o c B r o w s e r
●
5 . 8 . 2
L a t e s t
5 . 4 0 . 0
5 . 3 8 . 2
5 . 3 8 . 1
5 . 3 8 . 0
5 . 3 6 . 3
5 . 3 6 . 2
5 . 3 6 . 1
5 . 3 6 . 0
5 . 3 4 . 3
5 . 3 4 . 2
5 . 3 4 . 1
5 . 3 4 . 0
5 . 3 2 . 1
5 . 3 2 . 0
5 . 3 0 . 3
5 . 3 0 . 2
5 . 3 0 . 1
5 . 3 0 . 0
5 . 2 8 . 3
5 . 2 8 . 2
5 . 2 8 . 1
5 . 2 8 . 0
5 . 2 6 . 3
5 . 2 6 . 2
5 . 2 6 . 1
5 . 2 6 . 0
5 . 2 4 . 4
5 . 2 4 . 3
5 . 2 4 . 2
5 . 2 4 . 1
5 . 2 4 . 0
5 . 2 2 . 4
5 . 2 2 . 3
5 . 2 2 . 2
5 . 2 2 . 1
5 . 2 2 . 0
5 . 2 0 . 3
5 . 2 0 . 2
5 . 2 0 . 1
5 . 2 0 . 0
5 . 1 8 . 4
5 . 1 8 . 3
5 . 1 8 . 2
5 . 1 8 . 1
5 . 1 8 . 0
5 . 1 6 . 3
5 . 1 6 . 2
5 . 1 6 . 1
5 . 1 6 . 0
5 . 1 4 . 4
5 . 1 4 . 3
5 . 1 4 . 2
5 . 1 4 . 1
5 . 1 4 . 0
5 . 1 2 . 5
5 . 1 2 . 4
5 . 1 2 . 3
5 . 1 2 . 2
5 . 1 2 . 1
5 . 1 2 . 0
5 . 1 0 . 1
5 . 1 0 . 0
5 . 8 . 9
5 . 8 . 8
5 . 8 . 7
5 . 8 . 6
5 . 8 . 5
5 . 8 . 4
5 . 8 . 3
5 . 8 . 2
5 . 8 . 1
5 . 8 . 0
5 . 6 . 2
5 . 6 . 1
5 . 6 . 0
5 . 0 0 5 _ 0 4
5 . 0 0 5 _ 0 3
5 . 0 0 5 _ 0 2
5 . 0 0 5 _ 0 1
5 . 0 0 5
●
D e v
b l e a d
5 . 4 1 . 2
5 . 4 1 . 1
5 . 4 0 . 0 - R C 2
5 . 4 0 . 0 - R C 1
5 . 3 9 . 1 0
5 . 3 9 . 9
5 . 3 9 . 8
5 . 3 9 . 6
5 . 3 9 . 5
5 . 3 9 . 4
5 . 3 9 . 3
5 . 3 9 . 2
5 . 3 9 . 1
5 . 3 7 . 1 1
5 . 3 7 . 1 0
5 . 3 7 . 9
5 . 3 7 . 8
5 . 3 7 . 7
5 . 3 7 . 6
5 . 3 7 . 5
5 . 3 7 . 4
5 . 3 7 . 3
5 . 3 7 . 2
5 . 3 7 . 1
5 . 3 7 . 0
●
D o c u m e n t a t i o n
P e r l
I n t r o
T u t o r i a l s
F A Q s
R e f e r e n c e
O p e r a t o r s
F u n c t i o n s
V a r i a b l e s
M o d u l e s
U t i l i t i e s
C o m m u n i t y
H i s t o r y
E x p a n d
p e r l f a q 6
( s o u r c e ,
C P A N )
Y o u a r e v i e w i n g t h e v e r s i o n o f t h i s d o c u m e n t a t i o n f r o m P e r l 5 . 8 . 2 .
V i e w t h e l a t e s t v e r s i o n
●
N A M E
●
D E S C R I P T I O N
●
H o w c a n I h o p e t o u s e r e g u l a r e x p r e s s i o n s w i t h o u t c r e a t i n g i l l e g i b l e a n d u n m a i n t a i n a b l e c o d e ?
●
I ' m h a v i n g t r o u b l e m a t c h i n g o v e r m o r e t h a n o n e l i n e . W h a t ' s w r o n g ?
●
H o w c a n I p u l l o u t l i n e s b e t w e e n t w o p a t t e r n s t h a t a r e t h e m s e l v e s o n d i f f e r e n t l i n e s ?
●
I p u t a r e g u l a r e x p r e s s i o n i n t o $ / b u t i t d i d n ' t w o r k . W h a t ' s w r o n g ?
●
H o w d o I s u b s t i t u t e c a s e i n s e n s i t i v e l y o n t h e L H S w h i l e p r e s e r v i n g c a s e o n t h e R H S ?
●
H o w c a n I m a k e \ w m a t c h n a t i o n a l c h a r a c t e r s e t s ?
●
H o w c a n I m a t c h a l o c a l e - s m a r t v e r s i o n o f / [ a - z A - Z ] / ?
●
H o w c a n I q u o t e a v a r i a b l e t o u s e i n a r e g e x ?
●
W h a t i s / o r e a l l y f o r ?
●
H o w d o I u s e a r e g u l a r e x p r e s s i o n t o s t r i p C s t y l e c o m m e n t s f r o m a f i l e ?
●
C a n I u s e P e r l r e g u l a r e x p r e s s i o n s t o m a t c h b a l a n c e d t e x t ?
●
W h a t d o e s i t m e a n t h a t r e g e x e s a r e g r e e d y ? H o w c a n I g e t a r o u n d i t ?
●
H o w d o I p r o c e s s e a c h w o r d o n e a c h l i n e ?
●
H o w c a n I p r i n t o u t a w o r d - f r e q u e n c y o r l i n e - f r e q u e n c y s u m m a r y ?
●
H o w c a n I d o a p p r o x i m a t e m a t c h i n g ?
●
H o w d o I e f f i c i e n t l y m a t c h m a n y r e g u l a r e x p r e s s i o n s a t o n c e ?
●
W h y d o n ' t w o r d - b o u n d a r y s e a r c h e s w i t h \ b w o r k f o r m e ?
●
W h y d o e s u s i n g $ & , $ ` , o r $ ' s l o w m y p r o g r a m d o w n ?
●
W h a t g o o d i s \ G i n a r e g u l a r e x p r e s s i o n ?
●
A r e P e r l r e g e x e s D F A s o r N F A s ? A r e t h e y P O S I X c o m p l i a n t ?
●
W h a t ' s w r o n g w i t h u s i n g g r e p i n a v o i d c o n t e x t ?
●
H o w c a n I m a t c h s t r i n g s w i t h m u l t i b y t e c h a r a c t e r s ?
●
H o w d o I m a t c h a p a t t e r n t h a t i s s u p p l i e d b y t h e u s e r ?
●
A U T H O R A N D C O P Y R I G H T
# N A M E
p e r l f a q 6 - R e g u l a r E x p r e s s i o n s ( $ R e v i s i o n : 1 . 2 0 $ , $ D a t e : 2 0 0 3 / 0 1 / 0 3 2 0 : 0 5 : 2 8 $ )
# D E S C R I P T I O N
T h i s s e c t i o n i s s u r p r i s i n g l y s m a l l b e c a u s e t h e r e s t o f t h e F A Q i s l i t t e r e d w i t h a n s w e r s i n v o l v i n g r e g u l a r e x p r e s s i o n s . F o r e x a m p l e , d e c o d i n g a U R L a n d c h e c k i n g w h e t h e r s o m e t h i n g i s a n u m b e r a r e h a n d l e d w i t h r e g u l a r e x p r e s s i o n s , b u t t h o s e a n s w e r s a r e f o u n d e l s e w h e r e i n t h i s d o c u m e n t ( in p e r l f a q 9 : ` ` H o w d o I d e c o d e o r c r e a t e t h o s e % - e n c o d i n g s o n t h e w e b ' ' a n d p e r l f a q 4 : ` ` H o w d o I d e t e r m i n e w h e t h e r a s c a l a r i s a n u m b e r / w h o l e / i n t e g e r / f l o a t ' ' , t o b e p r e c i s e ) .
# H o w c a n I h o p e t o u s e r e g u l a r e x p r e s s i o n s w i t h o u t c r e a t i n g i l l e g i b l e a n d u n m a i n t a i n a b l e c o d e ?
T h r e e t e c h n i q u e s c a n m a k e r e g u l a r e x p r e s s i o n s m a i n t a i n a b l e a n d u n d e r s t a n d a b l e .
# C o m m e n t s O u t s i d e t h e R e g e x
D e s c r i b e w h a t y o u ' r e d o i n g a n d h o w y o u ' r e d o i n g i t , u s i n g n o r m a l P e r l c o m m e n t s .
# 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;
# C o m m e n t s I n s i d e t h e R e g e x
T h e / x
m o d i f i e r c a u s e s w h i t e s p a c e t o b e i g n o r e d i n a r e g e x p a t t e r n ( e x c e p t i n a c h a r a c t e r c l a s s ) , a n d a l s o a l l o w s y o u t o u s e n o r m a l c o m m e n t s t h e r e , t o o . A s y o u c a n i m a g i n e , w h i t e s p a c e a n d c o m m e n t s h e l p a l o t .
/ x
l e t s y o u t u r n t h i s :
s{<(?:[^>'"]*|".*?"|'.*?')+>}{}gs;
i n t o t h i s :
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
I t ' s s t i l l n o t q u i t e s o c l e a r a s p r o s e , b u t i t i s v e r y u s e f u l f o r d e s c r i b i n g t h e m e a n i n g o f e a c h p a r t o f t h e p a t t e r n .
# D i f f e r e n t D e l i m i t e r s
W h i l e w e n o r m a l l y t h i n k o f p a t t e r n s a s b e i n g d e l i m i t e d w i t h /
c h a r a c t e r s , t h e y c a n b e d e l i m i t e d b y a l m o s t a n y c h a r a c t e r . p e r l r e d e s c r i b e s t h i s . F o r e x a m p l e , t h e s / / /
a b o v e u s e s b r a c e s a s d e l i m i t e r s . S e l e c t i n g a n o t h e r d e l i m i t e r c a n a v o i d q u o t i n g t h e d e l i m i t e r w i t h i n t h e p a t t e r n :
s/\/usr\/local/\/usr\/share/g; # bad delimiter choice
s#/usr/local#/usr/share#g; # better
# I ' m h a v i n g t r o u b l e m a t c h i n g o v e r m o r e t h a n o n e l i n e . W h a t ' s w r o n g ?
E i t h e r y o u d o n ' t h a v e m o r e t h a n o n e l i n e i n t h e s t r i n g y o u ' r e l o o k i n g a t ( p r o b a b l y ) , o r e l s e y o u a r e n ' t u s i n g t h e c o r r e c t m o d i f i e r ( s ) o n y o u r p a t t e r n ( p o s s i b l y ) .
T h e r e a r e m a n y w a y s t o g e t m u l t i l i n e d a t a i n t o a s t r i n g . I f y o u w a n t i t t o h a p p e n a u t o m a t i c a l l y w h i l e r e a d i n g i n p u t , y o u ' l l w a n t t o s e t $ / ( p r o b a b l y t o ' ' f o r p a r a g r a p h s o r u n d e f
f o r t h e w h o l e f i l e ) t o a l l o w y o u t o r e a d m o r e t h a n o n e l i n e a t a t i m e .
R e a d p e r l r e t o h e l p y o u d e c i d e w h i c h o f / s
a n d / m
( o r b o t h ) y o u m i g h t w a n t t o u s e : / s
a l l o w s d o t t o i n c l u d e n e w l i n e , a n d / m
a l l o w s c a r e t a n d d o l l a r t o m a t c h n e x t t o a n e w l i n e , n o t j u s t a t t h e e n d o f t h e s t r i n g . Y o u d o n e e d t o m a k e s u r e t h a t y o u ' v e a c t u a l l y g o t a m u l t i l i n e s t r i n g i n t h e r e .
F o r e x a m p l e , t h i s p r o g r a m d e t e c t s d u p l i c a t e w o r d s , e v e n w h e n t h e y s p a n l i n e b r e a k s ( b u t n o t p a r a g r a p h o n e s ) . F o r t h i s e x a m p l e , w e d o n ' t n e e d / s
b e c a u s e w e a r e n ' t u s i n g d o t i n a r e g u l a r e x p r e s s i o n t h a t w e w a n t t o c r o s s l i n e b o u n d a r i e s . N e i t h e r d o w e n e e d / m
b e c a u s e w e a r e n ' t w a n t i n g c a r e t o r d o l l a r t o m a t c h a t a n y p o i n t i n s i d e t h e r e c o r d n e x t t o n e w l i n e s . B u t i t ' s i m p e r a t i v e t h a t $ / b e s e t t o s o m e t h i n g o t h e r t h a n t h e d e f a u l t , o r e l s e w e w o n ' t a c t u a l l y e v e r h a v e a m u l t i l i n e r e c o r d r e a d i n .
$/ = ''; # read in more whole paragraph, not just one line
while ( <> ) {
while ( /\b([\w'-]+)(\s+\1)+\b/gi ) { # word starts alpha
print "Duplicate $1 at paragraph $.\n";
}
}
H e r e ' s c o d e t h a t f i n d s s e n t e n c e s t h a t b e g i n w i t h " F r o m " ( w h i c h w o u l d b e m a n g l e d b y m a n y m a i l e r s ) :
$/ = ''; # read in more whole paragraph, not just one line
while ( <> ) {
while ( /^From /gm ) { # /m makes ^ match next to \n
print "leading from in paragraph $.\n";
}
}
H e r e ' s c o d e t h a t f i n d s e v e r y t h i n g b e t w e e n S T A R T a n d E N D i n a p a r a g r a p h :
undef $/; # read in whole file, not just one line or paragraph
while ( <> ) {
while ( /START(.*?)END/sgm ) { # /s makes . cross line boundaries
print "$1\n";
}
}
# H o w c a n I p u l l o u t l i n e s b e t w e e n t w o p a t t e r n s t h a t a r e t h e m s e l v e s o n d i f f e r e n t l i n e s ?
Y o u c a n u s e P e r l ' s s o m e w h a t e x o t i c . .
o p e r a t o r ( d o c u m e n t e d i n p e r l o p ) :
perl -ne 'print if /START/ .. /END/' file1 file2 ...
I f y o u w a n t e d t e x t a n d n o t l i n e s , y o u w o u l d u s e
perl -0777 -ne 'print "$1\n" while /START(.*?)END/gs' file1 file2 ...
B u t i f y o u w a n t n e s t e d o c c u r r e n c e s o f S T A R T
t h r o u g h E N D
, y o u ' l l r u n u p a g a i n s t t h e p r o b l e m d e s c r i b e d i n t h e q u e s t i o n i n t h i s s e c t i o n o n m a t c h i n g b a l a n c e d t e x t .
H e r e ' s a n o t h e r e x a m p l e o f u s i n g .
.
:
while (<>) {
$in_header = 1 .. /^$/;
$in_body = /^$/ .. eof();
# now choose between them
} continue {
reset if eof(); # fix $.
}
# I p u t a r e g u l a r e x p r e s s i o n i n t o $ / b u t i t d i d n ' t w o r k . W h a t ' s w r o n g ?
U p t o P e r l 5 . 8 . 0 , $ / h a s t o b e a s t r i n g . T h i s m a y c h a n g e i n 5 . 1 0 , b u t d o n ' t g e t y o u r h o p e s u p . U n t i l t h e n , y o u c a n u s e t h e s e e x a m p l e s i f y o u r e a l l y n e e d t o d o t h i s .
U s e t h e f o u r a r g u m e n t f o r m o f s y s r e a d t o c o n t i n u a l l y a d d t o a b u f f e r . A f t e r y o u a d d t o t h e b u f f e r , y o u c h e c k i f y o u h a v e a c o m p l e t e l i n e ( u s i n g y o u r r e g u l a r e x p r e s s i o n ) .
local $_ = "";
while( sysread FH, $_, 8192, length ) {
while( s/^((?s).*?)your_pattern/ ) {
my $record = $1;
# do stuff here.
}
}
You can do the same thing with foreach and a match using the
c flag and the \G anchor, if you do not mind your entire file
being in memory at the end.
local $_ = "";
while( sysread FH, $_, 8192, length ) {
foreach my $record ( m/\G((?s).*?)your_pattern/gc ) {
# do stuff here.
}
substr( $_, 0, pos ) = "" if pos;
}
# H o w d o I s u b s t i t u t e c a s e i n s e n s i t i v e l y o n t h e L H S w h i l e p r e s e r v i n g c a s e o n t h e R H S ?
H e r e ' s a l o v e l y P e r l i s h s o l u t i o n b y L a r r y R o s l e r . I t e x p l o i t s p r o p e r t i e s o f b i t w i s e x o r o n A S C I I s t r i n g s .
$_= "this is a TEsT case";
$old = 'test';
$new = 'success';
s{(\Q$old\E)}
{ uc $new | (uc $1 ^ $1) .
(uc(substr $1, -1) ^ substr $1, -1) x
(length($new) - length $1)
}egi;
print;
A n d h e r e i t i s a s a s u b r o u t i n e , m o d e l e d a f t e r t h e a b o v e :
sub preserve_case($$) {
my ($old, $new) = @_;
my $mask = uc $old ^ $old;
uc $new | $mask .
substr($mask, -1) x (length($new) - length($old))
}
$a = "this is a TEsT case";
$a =~ s/(test)/preserve_case($1, "success")/egi;
print "$a\n";
T h i s p r i n t s :
this is a SUcCESS case
A s a n a l t e r n a t i v e , t o k e e p t h e c a s e o f t h e r e p l a c e m e n t w o r d i f i t i s l o n g e r t h a n t h e o r i g i n a l , y o u c a n u s e t h i s c o d e , b y J e f f P i n y a n :
sub preserve_case {
my ($from, $to) = @_;
my ($lf, $lt) = map length, @_;
if ($lt < $lf) { $from = substr $from, 0, $lt }
else { $from .= substr $to, $lf }
return uc $to | ($from ^ uc $from);
}
T h i s c h a n g e s t h e s e n t e n c e t o " t h i s i s a S U c C e s s c a s e . "
J u s t t o s h o w t h a t C p r o g r a m m e r s c a n w r i t e C i n a n y p r o g r a m m i n g l a n g u a g e , i f y o u p r e f e r a m o r e C - l i k e s o l u t i o n , t h e f o l l o w i n g s c r i p t m a k e s t h e s u b s t i t u t i o n h a v e t h e s a m e c a s e , l e t t e r b y l e t t e r , a s t h e o r i g i n a l . ( I t a l s o h a p p e n s t o r u n a b o u t 2 4 0 % s l o w e r t h a n t h e P e r l i s h s o l u t i o n r u n s . ) I f t h e s u b s t i t u t i o n h a s m o r e c h a r a c t e r s t h a n t h e s t r i n g b e i n g s u b s t i t u t e d , t h e c a s e o f t h e l a s t c h a r a c t e r i s u s e d f o r t h e r e s t o f t h e s u b s t i t u t i o n .
# Original by Nathan Torkington, massaged by Jeffrey Friedl
#
sub preserve_case($$)
{
my ($old, $new) = @_;
my ($state) = 0; # 0 = no change; 1 = lc; 2 = uc
my ($i, $oldlen, $newlen, $c) = (0, length($old), length($new));
my ($len) = $oldlen < $newlen ? $oldlen : $newlen;
for ($i = 0; $i < $len; $i++) {
if ($c = substr($old, $i, 1), $c =~ /[\W\d_]/) {
$state = 0;
} elsif (lc $c eq $c) {
substr($new, $i, 1) = lc(substr($new, $i, 1));
$state = 1;
} else {
substr($new, $i, 1) = uc(substr($new, $i, 1));
$state = 2;
}
}
# finish up with any remaining new (for when new is longer than old)
if ($newlen > $oldlen) {
if ($state == 1) {
substr($new, $oldlen) = lc(substr($new, $oldlen));
} elsif ($state == 2) {
substr($new, $oldlen) = uc(substr($new, $oldlen));
}
}
return $new;
}
# H o w c a n I m a k e \ w
m a t c h n a t i o n a l c h a r a c t e r s e t s ?
P u t u s e l o c a l e ;
i n y o u r s c r i p t . T h e \ w c h a r a c t e r c l a s s i s t a k e n f r o m t h e c u r r e n t l o c a l e .
S e e p e r l l o c a l e f o r d e t a i l s .
# H o w c a n I m a t c h a l o c a l e - s m a r t v e r s i o n o f / [ a - z A - Z ] /
?
Y o u c a n u s e t h e P O S I X c h a r a c t e r c l a s s s y n t a x / [ [ : a l p h a : ] ] /
d o c u m e n t e d i n p e r l r e .
N o m a t t e r w h i c h l o c a l e y o u a r e i n , t h e a l p h a b e t i c c h a r a c t e r s a r e t h e c h a r a c t e r s i n \ w w i t h o u t t h e d i g i t s a n d t h e u n d e r s c o r e . A s a r e g e x , t h a t l o o k s l i k e / [ ^ \ W \ d
_ ] /
. I t s c o m p l e m e n t , t h e n o n - a l p h a b e t i c s , i s t h e n e v e r y t h i n g i n \ W a l o n g w i t h t h e d i g i t s a n d t h e u n d e r s c o r e , o r / [ \ W \ d _ ] /
.
# H o w c a n I q u o t e a v a r i a b l e t o u s e i n a r e g e x ?
T h e P e r l p a r s e r w i l l e x p a n d $ v a r i a b l e a n d @ v a r i a b l e r e f e r e n c e s i n r e g u l a r e x p r e s s i o n s u n l e s s t h e d e l i m i t e r i s a s i n g l e q u o t e . R e m e m b e r , t o o , t h a t t h e r i g h t - h a n d s i d e o f a s / / /
s u b s t i t u t i o n i s c o n s i d e r e d a d o u b l e - q u o t e d s t r i n g ( s e e p e r l o p f o r m o r e d e t a i l s ) . R e m e m b e r a l s o t h a t a n y r e g e x s p e c i a l c h a r a c t e r s w i l l b e a c t e d o n u n l e s s y o u p r e c e d e t h e s u b s t i t u t i o n w i t h \ Q . H e r e ' s a n e x a m p l e :
$string = "Placido P. Octopus";
$regex = "P.";
$string =~ s/$regex/Polyp/;
# $string is now "Polypacido P. Octopus"
B e c a u s e .
i s s p e c i a l i n r e g u l a r e x p r e s s i o n s , a n d c a n m a t c h a n y s i n g l e c h a r a c t e r , t h e r e g e x P .
h e r e h a s m a t c h e d t h e < P l > i n t h e o r i g i n a l s t r i n g .
T o e s c a p e t h e s p e c i a l m e a n i n g o f .
, w e u s e \ Q
:
$string = "Placido P. Octopus";
$regex = "P.";
$string =~ s/\Q$regex/Polyp/;
# $string is now "Placido Polyp Octopus"
T h e u s e o f \ Q
c a u s e s t h e < . > i n t h e r e g e x t o b e t r e a t e d a s a r e g u l a r c h a r a c t e r , s o t h a t P .
m a t c h e s a P
f o l l o w e d b y a d o t .
# W h a t i s / o
r e a l l y f o r ?
U s i n g a v a r i a b l e i n a r e g u l a r e x p r e s s i o n m a t c h f o r c e s a r e - e v a l u a t i o n ( a n d p e r h a p s r e c o m p i l a t i o n ) e a c h t i m e t h e r e g u l a r e x p r e s s i o n i s e n c o u n t e r e d . T h e / o
m o d i f i e r l o c k s i n t h e r e g e x t h e f i r s t t i m e i t ' s u s e d . T h i s a l w a y s h a p p e n s i n a c o n s t a n t r e g u l a r e x p r e s s i o n , a n d i n f a c t , t h e p a t t e r n w a s c o m p i l e d i n t o t h e i n t e r n a l f o r m a t a t t h e s a m e t i m e y o u r e n t i r e p r o g r a m w a s .
U s e o f / o
i s i r r e l e v a n t u n l e s s v a r i a b l e i n t e r p o l a t i o n i s u s e d i n t h e p a t t e r n , a n d i f s o , t h e r e g e x e n g i n e w i l l n e i t h e r k n o w n o r c a r e w h e t h e r t h e v a r i a b l e s c h a n g e a f t e r t h e p a t t e r n i s e v a l u a t e d t h e v e r y f i r s t t i m e .
/ o
i s o f t e n u s e d t o g a i n a n e x t r a m e a s u r e o f e f f i c i e n c y b y n o t p e r f o r m i n g s u b s e q u e n t e v a l u a t i o n s w h e n y o u k n o w i t w o n ' t m a t t e r ( b e c a u s e y o u k n o w t h e v a r i a b l e s w o n ' t c h a n g e ) , o r m o r e r a r e l y , w h e n y o u d o n ' t w a n t t h e r e g e x t o n o t i c e i f t h e y d o .
F o r e x a m p l e , h e r e ' s a " p a r a g r e p " p r o g r a m :
$/ = ''; # paragraph mode
$pat = shift;
while (<>) {
print if /$pat/o;
}
W h i l e t h i s a c t u a l l y c a n b e d o n e , i t ' s m u c h h a r d e r t h a n y o u ' d t h i n k . F o r e x a m p l e , t h i s o n e - l i n e r
perl -0777 -pe 's{/\*.*?\*/}{}gs' foo.c
w i l l w o r k i n m a n y b u t n o t a l l c a s e s . Y o u s e e , i t ' s t o o s i m p l e - m i n d e d f o r c e r t a i n k i n d s o f C p r o g r a m s , i n p a r t i c u l a r , t h o s e w i t h w h a t a p p e a r t o b e c o m m e n t s i n q u o t e d s t r i n g s . F o r t h a t , y o u ' d n e e d s o m e t h i n g l i k e t h i s , c r e a t e d b y J e f f r e y F r i e d l a n d l a t e r m o d i f i e d b y F r e d C u r t i s .
$/ = undef;
$_ = <>;
s#/\*[^*]*\*+([^/*][^*]*\*+)*/|("(\\.|[^"\\])*"|'(\\.|[^'\\])*'|.[^/"'\\]*)#$2#gs
print;
T h i s c o u l d , o f c o u r s e , b e m o r e l e g i b l y w r i t t e n w i t h t h e / x
m o d i f i e r , a d d i n g w h i t e s p a c e a n d c o m m e n t s . H e r e i t i s e x p a n d e d , c o u r t e s y o f F r e d C u r t i s .
s{
/\* ## Start of /* ... */ comment
[^*]*\*+ ## Non-* followed by 1-or-more *'s
(
[^/*][^*]*\*+
)* ## 0-or-more things which don't start with /
## but do end with '*'
/ ## End of /* ... */ comment
| ## OR various things which aren't comments:
(
" ## Start of " ... " string
(
\\. ## Escaped char
| ## OR
[^"\\] ## Non "\
)*
" ## End of " ... " string
| ## OR
' ## Start of ' ... ' string
(
\\. ## Escaped char
| ## OR
[^'\\] ## Non '\
)*
' ## End of ' ... ' string
| ## OR
. ## Anything other char
[^/"'\\]* ## Chars which doesn't start a comment, string or escape
)
}{$2}gxs;
A s l i g h t m o d i f i c a t i o n a l s o r e m o v e s C + + c o m m e n t s :
s#/\*[^*]*\*+([^/*][^*]*\*+)*/|//[^\n]*|("(\\.|[^"\\])*"|'(\\.|[^'\\])*'|.[^/"'\\]*)#$2#gs;
# C a n I u s e P e r l r e g u l a r e x p r e s s i o n s t o m a t c h b a l a n c e d t e x t ?
H i s t o r i c a l l y , P e r l r e g u l a r e x p r e s s i o n s w e r e n o t c a p a b l e o f m a t c h i n g b a l a n c e d t e x t . A s o f m o r e r e c e n t v e r s i o n s o f p e r l i n c l u d i n g 5 . 6 . 1 e x p e r i m e n t a l f e a t u r e s h a v e b e e n a d d e d t h a t m a k e i t p o s s i b l e t o d o t h i s . L o o k a t t h e d o c u m e n t a t i o n f o r t h e ( ?? { } ) c o n s t r u c t i n r e c e n t p e r l r e m a n u a l p a g e s t o s e e a n e x a m p l e o f m a t c h i n g b a l a n c e d p a r e n t h e s e s . B e s u r e t o t a k e s p e c i a l n o t i c e o f t h e w a r n i n g s p r e s e n t i n t h e m a n u a l b e f o r e m a k i n g u s e o f t h i s f e a t u r e .
C P A N c o n t a i n s m a n y m o d u l e s t h a t c a n b e u s e f u l f o r m a t c h i n g t e x t d e p e n d i n g o n t h e c o n t e x t . D a m i a n C o n w a y p r o v i d e s s o m e u s e f u l p a t t e r n s i n R e g e x p : : C o m m o n . T h e m o d u l e T e x t : : B a l a n c e d p r o v i d e s a g e n e r a l s o l u t i o n t o t h i s p r o b l e m .
O n e o f t h e c o m m o n a p p l i c a t i o n s o f b a l a n c e d t e x t m a t c h i n g i s w o r k i n g w i t h X M L a n d H T M L . T h e r e a r e m a n y m o d u l e s a v a i l a b l e t h a t s u p p o r t t h e s e n e e d s . T w o e x a m p l e s a r e H T M L : : P a r s e r a n d X M L : : P a r s e r . T h e r e a r e m a n y o t h e r s .
A n e l a b o r a t e s u b r o u t i n e ( f o r 7 - b i t A S C I I o n l y ) t o p u l l o u t b a l a n c e d a n d p o s s i b l y n e s t e d s i n g l e c h a r s , l i k e `
a n d '
, {
a n d }
, o r (
a n d )
c a n b e f o u n d i n h t t p : / / w w w . c p a n . o r g / a u t h o r s / i d / T O M C / s c r i p t s / p u l l _ q u o t e s . g z .
T h e C : : S c a n m o d u l e f r o m C P A N a l s o c o n t a i n s s u c h s u b s f o r i n t e r n a l u s e , b u t t h e y a r e u n d o c u m e n t e d .
# W h a t d o e s i t m e a n t h a t r e g e x e s a r e g r e e d y ? H o w c a n I g e t a r o u n d i t ?
M o s t p e o p l e m e a n t h a t g r e e d y r e g e x e s m a t c h a s m u c h a s t h e y c a n . T e c h n i c a l l y s p e a k i n g , i t ' s a c t u a l l y t h e q u a n t i f i e r s ( ?
, *
, +
, { }
) t h a t a r e g r e e d y r a t h e r t h a n t h e w h o l e p a t t e r n ; P e r l p r e f e r s l o c a l g r e e d a n d i m m e d i a t e g r a t i f i c a t i o n t o o v e r a l l g r e e d . T o g e t n o n - g r e e d y v e r s i o n s o f t h e s a m e q u a n t i f i e r s , u s e ( ??
, * ?
, + ?
, { } ?
) .
A n e x a m p l e :
$s1 = $s2 = "I am very very cold";
$s1 =~ s/ve.*y //; # I am cold
$s2 =~ s/ve.*?y //; # I am very cold
N o t i c e h o w t h e s e c o n d s u b s t i t u t i o n s t o p p e d m a t c h i n g a s s o o n a s i t e n c o u n t e r e d " y " . T h e * ?
q u a n t i f i e r e f f e c t i v e l y t e l l s t h e r e g u l a r e x p r e s s i o n e n g i n e t o f i n d a m a t c h a s q u i c k l y a s p o s s i b l e a n d p a s s c o n t r o l o n t o w h a t e v e r i s n e x t i n l i n e , l i k e y o u w o u l d i f y o u w e r e p l a y i n g h o t p o t a t o .
# H o w d o I p r o c e s s e a c h w o r d o n e a c h l i n e ?
U s e t h e s p l i t f u n c t i o n :
while (<>) {
foreach $word ( split ) {
# do something with $word here
}
}
N o t e t h a t t h i s i s n ' t r e a l l y a w o r d i n t h e E n g l i s h s e n s e ; i t ' s j u s t c h u n k s o f c o n s e c u t i v e n o n - w h i t e s p a c e c h a r a c t e r s .
T o w o r k w i t h o n l y a l p h a n u m e r i c s e q u e n c e s ( i n c l u d i n g u n d e r s c o r e s ) , y o u m i g h t c o n s i d e r
while (<>) {
foreach $word (m/(\w+)/g) {
# do something with $word here
}
}
# H o w c a n I p r i n t o u t a w o r d - f r e q u e n c y o r l i n e - f r e q u e n c y s u m m a r y ?
T o d o t h i s , y o u h a v e t o p a r s e o u t e a c h w o r d i n t h e i n p u t s t r e a m . W e ' l l p r e t e n d t h a t b y w o r d y o u m e a n c h u n k o f a l p h a b e t i c s , h y p h e n s , o r a p o s t r o p h e s , r a t h e r t h a n t h e n o n - w h i t e s p a c e c h u n k i d e a o f a w o r d g i v e n i n t h e p r e v i o u s q u e s t i o n :
while (<>) {
while ( /(\b[^\W_\d][\w'-]+\b)/g ) { # misses "`sheep'"
$seen{$1}++;
}
}
while ( ($word, $count) = each %seen ) {
print "$count $word\n";
}
I f y o u w a n t e d t o d o t h e s a m e t h i n g f o r l i n e s , y o u w o u l d n ' t n e e d a r e g u l a r e x p r e s s i o n :
while (<>) {
$seen{$_}++;
}
while ( ($line, $count) = each %seen ) {
print "$count $line";
}
I f y o u w a n t t h e s e o u t p u t i n a s o r t e d o r d e r , s e e p e r l f a q 4 : ` ` H o w d o I s o r t a h a s h ( o p t i o n a l l y b y v a l u e i n s t e a d o f k e y ) ? ' ' .
# H o w c a n I d o a p p r o x i m a t e m a t c h i n g ?
S e e t h e m o d u l e S t r i n g : : A p p r o x a v a i l a b l e f r o m C P A N .
# H o w d o I e f f i c i e n t l y m a t c h m a n y r e g u l a r e x p r e s s i o n s a t o n c e ?
T h e f o l l o w i n g i s e x t r e m e l y i n e f f i c i e n t :
# 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;
}
}
}
T h a t ' s b e c a u s e P e r l h a s t o r e c o m p i l e a l l t h o s e p a t t e r n s f o r e a c h o f t h e l i n e s o f t h e f i l e . A s o f t h e 5 . 0 0 5 r e l e a s e , t h e r e ' s a m u c h b e t t e r a p p r o a c h , o n e w h i c h m a k e s u s e o f t h e n e w q r / /
o p e r a t o r :
# 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/;
}
}
# W h y d o n ' t w o r d - b o u n d a r y s e a r c h e s w i t h \ b
w o r k f o r m e ?
T w o c o m m o n m i s c o n c e p t i o n s a r e t h a t \ b
i s a s y n o n y m f o r \ s +
a n d t h a t i t ' s t h e e d g e b e t w e e n w h i t e s p a c e c h a r a c t e r s a n d n o n - w h i t e s p a c e c h a r a c t e r s . N e i t h e r i s c o r r e c t . \ b
i s t h e p l a c e b e t w e e n a \ w
c h a r a c t e r a n d a \ W
c h a r a c t e r ( t h a t i s , \ b
i s t h e e d g e o f a " w o r d " ) . I t ' s a z e r o - w i d t h a s s e r t i o n , j u s t l i k e ^
, $
, a n d a l l t h e o t h e r a n c h o r s , s o i t d o e s n ' t c o n s u m e a n y c h a r a c t e r s . p e r l r e d e s c r i b e s t h e b e h a v i o r o f a l l t h e r e g e x m e t a c h a r a c t e r s .
H e r e a r e e x a m p l e s o f t h e i n c o r r e c t a p p l i c a t i o n o f \ b
, w i t h f i x e s :
"two words" =~ /(\w+)\b(\w+)/; # WRONG
"two words" =~ /(\w+)\s+(\w+)/; # right
" =matchless= text" =~ /\b=(\w+)=\b/; # WRONG
" =matchless= text" =~ /=(\w+)=/; # right
A l t h o u g h t h e y m a y n o t d o w h a t y o u t h o u g h t t h e y d i d , \ b
a n d \ B
c a n s t i l l b e q u i t e u s e f u l . F o r a n e x a m p l e o f t h e c o r r e c t u s e o f \ b
, s e e t h e e x a m p l e o f m a t c h i n g d u p l i c a t e w o r d s o v e r m u l t i p l e l i n e s .
A n e x a m p l e o f u s i n g \ B
i s t h e p a t t e r n \ B i s \ B
. T h i s w i l l f i n d o c c u r r e n c e s o f " i s " o n t h e i n s i d e s o f w o r d s o n l y , a s i n " t h i s t l e " , b u t n o t " t h i s " o r " i s l a n d " .
# W h y d o e s u s i n g $ & , $ ` , o r $ ' s l o w m y p r o g r a m d o w n ?
O n c e P e r l s e e s t h a t y o u n e e d o n e o f t h e s e v a r i a b l e s a n y w h e r e i n t h e p r o g r a m , i t p r o v i d e s t h e m o n e a c h a n d e v e r y p a t t e r n m a t c h . T h e s a m e m e c h a n i s m t h a t h a n d l e s t h e s e p r o v i d e s f o r t h e u s e o f $ 1 , $ 2 , e t c . , s o y o u p a y t h e s a m e p r i c e f o r e a c h r e g e x t h a t c o n t a i n s c a p t u r i n g p a r e n t h e s e s . I f y o u n e v e r u s e $ & , e t c . , i n y o u r s c r i p t , t h e n r e g e x e s w i t h o u t c a p t u r i n g p a r e n t h e s e s w o n ' t b e p e n a l i z e d . S o a v o i d $ & , $ ' , a n d $ ` i f y o u c a n , b u t i f y o u c a n ' t , o n c e y o u ' v e u s e d t h e m a t a l l , u s e t h e m a t w i l l b e c a u s e y o u ' v e a l r e a d y p a i d t h e p r i c e . R e m e m b e r t h a t s o m e a l g o r i t h m s r e a l l y a p p r e c i a t e t h e m . A s o f t h e 5 . 0 0 5 r e l e a s e . t h e $ & v a r i a b l e i s n o l o n g e r " e x p e n s i v e " t h e w a y t h e o t h e r t w o a r e .
# W h a t g o o d i s \ G
i n a r e g u l a r e x p r e s s i o n ?
Y o u u s e t h e \ G
a n c h o r t o s t a r t t h e n e x t m a t c h o n t h e s a m e s t r i n g w h e r e t h e l a s t m a t c h l e f t o f f . T h e r e g u l a r e x p r e s s i o n e n g i n e c a n n o t s k i p o v e r a n y c h a r a c t e r s t o f i n d t h e n e x t m a t c h w i t h t h i s a n c h o r , s o \ G
i s s i m i l a r t o t h e b e g i n n i n g o f s t r i n g a n c h o r , ^
. T h e \ G
a n c h o r i s t y p i c a l l y u s e d w i t h t h e g
f l a g . I t u s e s t h e v a l u e o f p o s ( ) a s t h e p o s i t i o n t o s t a r t t h e n e x t m a t c h . A s t h e m a t c h o p e r a t o r m a k e s s u c c e s s i v e m a t c h e s , i t u p d a t e s p o s ( ) w i t h t h e p o s i t i o n o f t h e n e x t c h a r a c t e r p a s t t h e l a s t m a t c h ( o r t h e f i r s t c h a r a c t e r o f t h e n e x t m a t c h , d e p e n d i n g o n h o w y o u l i k e t o l o o k a t i t ) . E a c h s t r i n g h a s i t s o w n p o s ( ) v a l u e .
S u p p o s e y o u w a n t t o m a t c h a l l o f c o n s e c t i v e p a i r s o f d i g i t s i n a s t r i n g l i k e " 1 1 2 2 a 4 4 " a n d s t o p m a t c h i n g w h e n y o u e n c o u n t e r n o n - d i g i t s . Y o u w a n t t o m a t c h 11
a n d 22
b u t t h e l e t t e r < a > s h o w s u p b e t w e e n 22
a n d 44
a n d y o u w a n t t o s t o p a t a
. S i m p l y m a t c h i n g p a i r s o f d i g i t s s k i p s o v e r t h e a
a n d s t i l l m a t c h e s 44
.
$_ = "1122a44";
my @pairs = m/(\d\d)/g; # qw( 11 22 44 )
I f y o u u s e t h e \ G a n c h o r , y o u f o r c e t h e m a t c h a f t e r 22
t o s t a r t w i t h t h e a
. T h e r e g u l a r e x p r e s s i o n c a n n o t m a t c h t h e r e s i n c e i t d o e s n o t f i n d a d i g i t , s o t h e n e x t m a t c h f a i l s a n d t h e m a t c h o p e r a t o r r e t u r n s t h e p a i r s i t a l r e a d y f o u n d .
$_ = "1122a44";
my @pairs = m/\G(\d\d)/g; # qw( 11 22 )
Y o u c a n a l s o u s e t h e \ G
a n c h o r i n s c a l a r c o n t e x t . Y o u s t i l l n e e d t h e g
f l a g .
$_ = "1122a44";
while( m/\G(\d\d)/g )
{
print "Found $1\n";
}
A f t e r t h e m a t c h f a i l s a t t h e l e t t e r a
, p e r l r e s e t s p o s ( ) a n d t h e n e x t m a t c h o n t h e s a m e s t r i n g s t a r t s a t t h e b e g i n n i n g .
$_ = "1122a44";
while( m/\G(\d\d)/g )
{
print "Found $1\n";
}
print "Found $1 after while" if m/(\d\d)/g; # finds "11"
Y o u c a n d i s a b l e p o s ( ) r e s e t s o n f a i l w i t h t h e c
f l a g . S u b s e q u e n t m a t c h e s s t a r t w h e r e t h e l a s t s u c c e s s f u l m a t c h e n d e d ( t h e v a l u e o f p o s ( ) ) e v e n i f a m a t c h o n t h e s a m e s t r i n g a s f a i l e d i n t h e m e a n t i m e . I n t h i s c a s e , t h e m a t c h a f t e r t h e w h i l e ( ) l o o p s t a r t s a t t h e a
( w h e r e t h e l a s t m a t c h s t o p p e d ) , a n d s i n c e i t d o e s n o t u s e a n y a n c h o r i t c a n s k i p o v e r t h e a
t o f i n d " 4 4 " .
$_ = "1122a44";
while( m/\G(\d\d)/gc )
{
print "Found $1\n";
}
print "Found $1 after while" if m/(\d\d)/g; # finds "44"
T y p i c a l l y y o u u s e t h e \ G
a n c h o r w i t h t h e c
f l a g w h e n y o u w a n t t o t r y a d i f f e r e n t m a t c h i f o n e f a i l s , s u c h a s i n a t o k e n i z e r . J e f f r e y F r i e d l o f f e r s t h i s e x a m p l e w h i c h w o r k s i n 5 . 0 0 4 o r l a t e r .
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; };
}
}
F o r e a c h l i n e , t h e P A R S E R l o o p f i r s t t r i e s t o m a t c h a s e r i e s o f d i g i t s f o l l o w e d b y a w o r d b o u n d a r y . T h i s m a t c h h a s t o s t a r t a t t h e p l a c e t h e l a s t m a t c h l e f t o f f ( o r t h e b e g i n n i n g o f t h e s t r i n g o n t h e f i r s t m a t c h ) . S i n c e m / \
G ( \ d + \ b ) / g c x
u s e s t h e c
f l a g , i f t h e s t r i n g d o e s n o t m a t c h t h a t r e g u l a r e x p r e s s i o n , p e r l d o e s n o t r e s e t p o s ( ) a n d t h e n e x t m a t c h s t a r t s a t t h e s a m e p o s i t i o n t o t r y a d i f f e r e n t p a t t e r n .
# A r e P e r l r e g e x e s D F A s o r N F A s ? A r e t h e y P O S I X c o m p l i a n t ?
W h i l e i t ' s t r u e t h a t P e r l ' s r e g u l a r e x p r e s s i o n s r e s e m b l e t h e D F A s ( d e t e r m i n i s t i c f i n i t e a u t o m a t a ) o f t h e e g r e p ( 1 ) p r o g r a m , t h e y a r e i n f a c t i m p l e m e n t e d a s N F A s ( n o n - d e t e r m i n i s t i c f i n i t e a u t o m a t a ) t o a l l o w b a c k t r a c k i n g a n d b a c k r e f e r e n c i n g . A n d t h e y a r e n ' t P O S I X - s t y l e e i t h e r , b e c a u s e t h o s e g u a r a n t e e w o r s t - c a s e b e h a v i o r f o r a l l c a s e s . ( I t s e e m s t h a t s o m e p e o p l e p r e f e r g u a r a n t e e s o f c o n s i s t e n c y , e v e n w h e n w h a t ' s g u a r a n t e e d i s s l o w n e s s . ) S e e t h e b o o k " M a s t e r i n g R e g u l a r E x p r e s s i o n s " ( f r o m O ' R e i l l y ) b y J e f f r e y F r i e d l f o r a l l t h e d e t a i l s y o u c o u l d e v e r h o p e t o k n o w o n t h e s e m a t t e r s ( a f u l l c i t a t i o n a p p e a r s i n p e r l f a q 2 ) .
# W h a t ' s w r o n g w i t h u s i n g g r e p i n a v o i d c o n t e x t ?
T h e p r o b l e m i s t h a t g r e p b u i l d s a r e t u r n l i s t , r e g a r d l e s s o f t h e c o n t e x t . T h i s m e a n s y o u ' r e m a k i n g P e r l g o t o t h e t r o u b l e o f b u i l d i n g a l i s t t h a t y o u t h e n j u s t t h r o w a w a y . I f t h e l i s t i s l a r g e , y o u w a s t e b o t h t i m e a n d s p a c e . I f y o u r i n t e n t i s t o i t e r a t e o v e r t h e l i s t , t h e n u s e a f o r l o o p f o r t h i s p u r p o s e .
I n p e r l s o l d e r t h a n 5 . 8 . 1 , m a p s u f f e r s f r o m t h i s p r o b l e m a s w e l l . B u t s i n c e 5 . 8 . 1 , t h i s h a s b e e n f i x e d , a n d m a p i s c o n t e x t a w a r e - i n v o i d c o n t e x t , n o l i s t s a r e c o n s t r u c t e d .
# H o w c a n I m a t c h s t r i n g s w i t h m u l t i b y t e c h a r a c t e r s ?
S t a r t i n g f r o m P e r l 5 . 6 P e r l h a s h a d s o m e l e v e l o f m u l t i b y t e c h a r a c t e r s u p p o r t . P e r l 5 . 8 o r l a t e r i s r e c o m m e n d e d . S u p p o r t e d m u l t i b y t e c h a r a c t e r r e p e r t o i r e s i n c l u d e U n i c o d e , a n d l e g a c y e n c o d i n g s t h r o u g h t h e E n c o d e m o d u l e . S e e p e r l u n i i n t r o , p e r l u n i c o d e , a n d E n c o d e .
I f y o u a r e s t u c k w i t h o l d e r P e r l s , y o u c a n d o U n i c o d e w i t h t h e U
n i c o d e : : S t r i n g
m o d u l e , a n d c h a r a c t e r c o n v e r s i o n s u s i n g t h e U n i c o
d e : : M a p 8
a n d U n i c o d e : : M a p
m o d u l e s . I f y o u a r e u s i n g J a p a n e s e e n c o d i n g s , y o u m i g h t t r y u s i n g t h e j p e r l 5 . 0 0 5 _ 0 3 .
F i n a l l y , t h e f o l l o w i n g s e t o f a p p r o a c h e s w a s o f f e r e d b y J e f f r e y F r i e d l , w h o s e a r t i c l e i n i s s u e # 5 o f T h e P e r l J o u r n a l t a l k s a b o u t t h i s v e r y m a t t e r .
L e t ' s s u p p o s e y o u h a v e s o m e w e i r d M a r t i a n e n c o d i n g w h e r e p a i r s o f A S C I I u p p e r c a s e l e t t e r s e n c o d e s i n g l e M a r t i a n l e t t e r s ( i . e . t h e t w o b y t e s " C V " m a k e a s i n g l e M a r t i a n l e t t e r , a s d o t h e t w o b y t e s " S G " , " V S " , " X X " , e t c . ) . O t h e r b y t e s r e p r e s e n t s i n g l e c h a r a c t e r s , j u s t l i k e A S C I I .
S o , t h e s t r i n g o f M a r t i a n " I a m C V S G X X ! " u s e s 1 2 b y t e s t o e n c o d e t h e n i n e c h a r a c t e r s ' I ' , ' ' , ' a ' , ' m ' , ' ' , ' C V ' , ' S G ' , ' X X ' , ' ! ' .
N o w , s a y y o u w a n t t o s e a r c h f o r t h e s i n g l e c h a r a c t e r / G X /
. P e r l d o e s n ' t k n o w a b o u t M a r t i a n , s o i t ' l l f i n d t h e t w o b y t e s " G X " i n t h e " I a m C V S G X X ! " s t r i n g , e v e n t h o u g h t h a t c h a r a c t e r i s n ' t t h e r e : i t j u s t l o o k s l i k e i t i s b e c a u s e " S G " i s n e x t t o " X X " , b u t t h e r e ' s n o r e a l " G X " . T h i s i s a b i g p r o b l e m .
H e r e a r e a f e w w a y s , a l l p a i n f u l , t o d e a l w i t h i t :
$martian =~ s/([A-Z][A-Z])/ $1 /g; # Make sure adjacent ``martian''
# bytes are no longer adjacent.
print "found GX!\n" if $martian =~ /GX/;
O r l i k e t h i s :
@chars = $martian =~ m/([A-Z][A-Z]|[^A-Z])/g;
# above is conceptually similar to: @chars = $text =~ m/(.)/g;
#
foreach $char (@chars) {
print "found GX!\n", last if $char eq 'GX';
}
O r l i k e t h i s :
while ($martian =~ m/\G([A-Z][A-Z]|.)/gs) { # \G probably unneeded
print "found GX!\n", last if $1 eq 'GX';
}
H e r e ' s a n o t h e r , s l i g h t l y l e s s p a i n f u l , w a y t o d o i t f r o m B e n j a m i n G o l d b e r g :
$martian =~ m/
(?!<[A-Z])
(?:[A-Z][A-Z])*?
GX
/x;
T h i s s u c c e e d s i f t h e " m a r t i a n " c h a r a c t e r G X i s i n t h e s t r i n g , a n d f a i l s o t h e r w i s e . I f y o u d o n ' t l i k e u s i n g ( ?! < ) , y o u c a n r e p l a c e ( ?! < [ A - Z ] ) w i t h ( ? : ^ | [ ^ A - Z ] ) .
I t d o e s h a v e t h e d r a w b a c k o f p u t t i n g t h e w r o n g t h i n g i n $ - [ 0 ] a n d $ + [ 0 ] , b u t t h i s u s u a l l y c a n b e w o r k e d a r o u n d .
# H o w d o I m a t c h a p a t t e r n t h a t i s s u p p l i e d b y t h e u s e r ?
W e l l , i f i t ' s r e a l l y a p a t t e r n , t h e n j u s t u s e
chomp($pattern = <STDIN>);
if ($line =~ /$pattern/) { }
A l t e r n a t i v e l y , s i n c e y o u h a v e n o g u a r a n t e e t h a t y o u r u s e r e n t e r e d a v a l i d r e g u l a r e x p r e s s i o n , t r a p t h e e x c e p t i o n t h i s w a y :
if (eval { $line =~ /$pattern/ }) { }
I f a l l y o u r e a l l y w a n t t o s e a r c h f o r a s t r i n g , n o t a p a t t e r n , t h e n y o u s h o u l d e i t h e r u s e t h e i n d e x ( ) f u n c t i o n , w h i c h i s m a d e f o r s t r i n g s e a r c h i n g , o r i f y o u c a n ' t b e d i s a b u s e d o f u s i n g a p a t t e r n m a t c h o n a n o n - p a t t e r n , t h e n b e s u r e t o u s e \ Q
. . . \ E
, d o c u m e n t e d i n p e r l r e .
$pattern = <STDIN>;
open (FILE, $input) or die "Couldn't open input $input: $!; aborting";
while (<FILE>) {
print if /\Q$pattern\E/;
}
close FILE;
# A U T H O R A N D C O P Y R I G H T
C o p y r i g h t ( c ) 1 9 9 7 - 2 0 0 2 T o m C h r i s t i a n s e n a n d N a t h a n T o r k i n g t o n . A l l r i g h t s r e s e r v e d .
T h i s d o c u m e n t a t i o n i s f r e e ; y o u c a n r e d i s t r i b u t e i t a n d / o r m o d i f y i t u n d e r t h e s a m e t e r m s a s P e r l i t s e l f .
I r r e s p e c t i v e o f i t s d i s t r i b u t i o n , a l l c o d e e x a m p l e s i n t h i s f i l e a r e h e r e b y p l a c e d i n t o t h e p u b l i c d o m a i n . Y o u a r e p e r m i t t e d a n d e n c o u r a g e d t o u s e t h i s c o d e i n y o u r o w n p r o g r a m s f o r f u n o r f o r p r o f i t a s y o u s e e f i t . A s i m p l e c o m m e n t i n t h e c o d e g i v i n g c r e d i t w o u l d b e c o u r t e o u s b u t i s n o t r e q u i r e d .
P e r l d o c B r o w s e r i s m a i n t a i n e d b y D a n B o o k ( D B O O K ) . P l e a s e c o n t a c t h i m v i a t h e G i t H u b i s s u e t r a c k e r or e m a i l r e g a r d i n g a n y i s s u e s w i t h t h e s i t e i t s e l f , s e a r c h , o r r e n d e r i n g o f d o c u m e n t a t i o n .
T h e P e r l d o c u m e n t a t i o n i s m a i n t a i n e d b y t h e P e r l 5 P o r t e r s i n t h e d e v e l o p m e n t o f P e r l . P l e a s e c o n t a c t t h e m v i a t h e P e r l i s s u e t r a c k e r , t h e m a i l i n g l i s t , o r I R C t o r e p o r t a n y i s s u e s w i t h t h e c o n t e n t s o r f o r m a t o f t h e d o c u m e n t a t i o n .