

\" 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"
}

