\"
en el interior de una cadena.
Por ejemplo en "esta \"palabra\" va entre comillas"
.
Analice esta solución ¿Es correcta?:
DB<1> $stringre = qr{"(\\.|[^\\"])*"} DB<2> print $& if '"esta \"palabra\" va entre comillas"' =~ $stringre "esta \"palabra\" va entre comillas"
# ...
).
/* ... */
.).
Repase las secciones sobre expresiones regulares no ``greedy'' (p. ej. sección
3.1.1) y la sección 3.1.1.
Recuerde que, en una expresión regular,
la opción /s
hace que el punto '.'
empareje con un
retorno de carro \n
. Esto es, el punto ``casa'' con cualquier carácter.
Observe el siguiente ejemplo:
pl@nereida:~/src/perl/testing$ cat -n ccomments.pl 1 #!/usr/bin/perl -w 2 use strict; 3 4 sub showmatches { 5 my ($x, $re) = @_; 6 7 for (my $i = 0; $x =~ /$re/gsx; $i++) { 8 print "matching $i: $1\n"; 9 $i++; 10 } 11 } 12 13 my $x = <<'EOC'; 14 if (x) { 15 /* a comment */ return x + 1; /* another comment */ 16 } 17 else { 18 return x + 2; /* a last comment */ 19 } 20 EOC 21 22 print "\n************************\n"; 23 24 my $greedy = q{ ( 25 /\* # Abrir comentario 26 .* # Consumir caracteres (greedy) 27 \*/ # Cerrar comentario 28 ) 29 }; 30 print "Greedy:\n"; 31 showmatches($x, $greedy); 32 33 print "\n************************\n"; 34 35 my $lazy = q{ ( 36 /\* # Abrir comentario 37 .*? # Consumir caracteres (lazy) 38 \*/ # Cerrar comentario 39 ) 40 }; 41 print "Lazy:\n"; 42 showmatches($x, $lazy);Cuando se ejecuta produce:
pl@nereida:~/src/perl/testing$ ccomments.pl ************************ Greedy: matching 0: /* a comment */ return x + 1; /* another comment */ } else { return x + 2; /* a last comment */ ************************ Lazy: matching 0: /* a comment */ matching 2: /* another comment */ matching 4: /* a last comment */
Explique la conducta.
-1.32e-04
o .91
).
El siguiente ejemplo intenta ayudarle en la búsqueda de la solución:
lhp@nereida:~$ perl -de 0 DB<1> print "Si" if ('.5' =~ m{\d+}) Si DB<2> print "Si" if ('.5' =~ m{^\d+}) DB<3> print "Si" if '0.7' =~ m{^\d+(\.\d+)?(e[+-]?\d+)?$} Si DB<4> print "Si" if '.7' =~ m{^\d+(\.\d+)?(e[+-]?\d+)?$} DB<5> print "Si" if '1e2' =~ m{^\d+(\.\d+)?(e[+-]?\d+)?$} Si DB<6> print "Si " while 'ababa' =~ m{a}g Si Si Si DB<7> print "@a" if @a = 'ababa' =~ m{(a)}g a a a¿Sabría decir porque la respuesta al primer comando del depurador es
si
?.
INT
y FLOAT
.
Si la entrada contiene 3.5
el terminal debería ser (FLOAT, '3.5')
y no (INT, 3), ('.', '.'), (INT, 5)
.
nereida:~/doc/casiano/PLBOOK/PLBOOK> perl -MRegexp::Common -e 'print "$RE{num}{int}\n"' (?:(?:[+-]?)(?:[0123456789]+))Podemos hacer uso directo del hash
%RE
directamente
en las expresiones regulares aprovechando que estas interpolan
las variables en su interior:
nereida:/tmp> cat -n prueba.pl 1 #!/usr/bin/perl -w 2 use strict; 3 use Regexp::Common; 4 5 my $input = <>; 6 7 print "$&\n" if $input =~ /^$RE{num}{real}$/; nereida:/tmp> ./prueba.pl 23.45 23.45 nereida:/tmp> ./prueba.pl jshdf nereida:/tmp>
(terminal, valor)
devuelto por el scanner
a un par (terminal, [valor, número de línea ])
cuya
segunda componente es un array anónimo conteniendo
el valor y el número de línea en el que aparece el terminal.
El siguiente extracto de un analizador léxico muestra como hacerlo:
sub _Lexer { return('', undef) unless defined($input); #Skip blanks $input=~m{\G((?: \s+ # any white space char | \#[^\n]* # Perl like comments )+)}xsgc and do { my($blanks)=$1; #Maybe At EOF pos($input) >= length($input) and return('', undef); $tokenend += $blanks =~ tr/\n//; }; $tokenbegin = $tokenend; $input=~/\G(and)/gc and return($1, [$1, $tokenbegin]); $input=~/\G(?:[A-Za-z_][A-Za-z0-9_]*::)*([A-Za-z_][A-Za-z0-9_]*)/gc and do { return('IDENT', [$1, $tokenbegin]); }; .................... $input=~/\G{/gc and do { my($level,$from,$code); $from=pos($input); $level=1; while($input=~/([{}])/gc) { substr($input,pos($input)-1,1) eq '\\' #Quoted and next; $level += ($1 eq '{' ? 1 : -1) or last; } $level and _SyntaxError("Not closed open curly bracket { at $tokenbegin"); $code = substr($input,$from,pos($input)-$from-1); $tokenend+= $code=~tr/\n//; return('CODE', [$code, $tokenbegin]); }; #Always return something $input=~/\G(.)/sg and do { $1 eq "\n" and ++$tokenend; return ($1, [$1, $tokenbegin]); }; #At EOF return('', undef); }El operador
tr
ha sido utilizado para contar los retornos de carro
(descrito en la sección
3.5). El operador, ademas de reemplazar
devuelve el número de carácteres reeemplazados
o suprimidos:
$cuenta = $cielo =~ tr/*/*/; # cuenta el numero de estrellas en cieloPara aprender soluciones alternativas consulte
perldoc -q 'substring'
.
error
y fatal
introducidas en la sección anterior escriba una sola rutina
que recibe el nivel de severidad del error (parámetro $level
en el siguiente ejemplo)
y ejecuta la acción apropiada. El código de _SyntaxError
ilustra como hacerlo:
sub _SyntaxError { my($level,$message,$lineno)=@_; $message= "*". [ 'Warning', 'Error', 'Fatal' ]->[$level]. "* $message, at ". ($lineno < 0 ? "eof" : "line $lineno")." at file $filename\n"; $level > 1 and die $message; warn $message; $level > 0 and ++$nberr; $nberr == $max_errors and die "*Fatal* Too many errors detected.\n" }