Citando a perlre:
A conditional expression is a form of if-then-else statement that allows one to choose which patterns are to be matched, based on some condition.
There are two types of conditional expression:(?(condition)yes-regexp)
and(?(condition)yes-regexp|no-regexp)
.
(?(condition)yes-regexp)
is like anif () {}
statement in Perl. If the condition is true, the yes-regexp will be matched. If the condition is false, the yes-regexp will be skipped and Perl will move onto the next regexp element.
The second form
is like an if () {} else {}
statement in Perl. If the condition is true,
the yes-regexp will be matched, otherwise the no-regexp will be matched.
The condition can have several forms.
\integer
matched earlier in the regexp. The same thing
can be done with a name associated with a capture buffer, written as
(<name>)
or ('name')
.
(?...)
, either a lookahead, a lookbehind, or a code assertion.
(R)
or is being
called from some capturing group, referenced either by number (R1
,
or by name (R&name)
.
Una expresión condicional puede adoptar diversas formas.
La mas simple es un entero en paréntesis.
Es cierta si la correspondiente referencia
\integer
casó (también se puede usar un nombre
si se trata de un paréntesis con nombre).
En la expresión regular /^(.)(..)?(?(2)a|b)/
si el segundo paréntesis
casa, la cadena debe ir seguida de una a
, si no casa deberá ir seguida de
una b
:
DB<1> x 'hola' =~ /^(.)(..)?(?(2)a|b)/ 0 'h' 1 'ol' DB<2> x 'ha' =~ /^(.)(..)?(?(2)a|b)/ empty array DB<3> x 'hb' =~ /^(.)(..)?(?(2)a|b)/ 0 'h' 1 undef
La siguiente búsqueda casa con patrones de la forma
$x$x
o $x$y$y$x
:
pl@nereida:~/Lperltesting$ perl5.10.1 -wde 0 main::(-e:1): 0 DB<1> x 'aa' =~ m{^(\w+)(\w+)?(?(2)\2\1|\1)$} 0 'a' 1 undef DB<2> x 'abba' =~ m{^(\w+)(\w+)?(?(2)\2\1|\1)$} 0 'a' 1 'b' DB<3> x 'abbc' =~ m{^(\w+)(\w+)?(?(2)\2\1|\1)$} empty array DB<4> x 'juanpedropedrojuan' =~ m{^(\w+)(\w+)?(?(2)\2\1|\1)$} 0 'juan' 1 'pedro'
Una expresión condicional también puede ser un código:
DB<1> $a = 0; print "$&" if 'hola' =~ m{(?(?{$a})hola|adios)} # No hay matching DB<2> $a = 1; print "$&" if 'hola' =~ m{(?(?{$a})hola|adios)} hola
La siguiente expresión regular utiliza un condicional para forzar a que si una cadena comienza por un paréntesis abrir termina con un paréntesis cerrar. Si la cadena no comienza por paréntesis abrir no debe existir un paréntesis final de cierre:
pl@nereida:~/Lperltesting$ cat -n conditionalregexp.pl 1 #!/usr/local/lib/perl/5.10.1/bin//perl5.10.1 -w 2 use v5.10; 3 use strict; 4 5 my $r = qr{(?x) # ignore spaces 6 ^ 7 ( \( )? # may be it comes an open par 8 [^()]+ # no parenthesis 9 (?(1) # did we sart with par? 10 \) # if yes then close par 11 ) 12 $ 13 }; 14 say "<$&>" if '(abcd)' =~ $r; 15 say "<$&>" if 'abc' =~ $r; 16 say "<(abc> does not match" unless '(abc' =~ $r; 17 say "<abc)> does not match" unless 'abc)' =~ $r;
Al ejecutar este programa se obtiene:
pl@nereida:~/Lperltesting$ ./conditionalregexp.pl <(abcd)> <abc> <(abc> does not match <abc)> does not match
El siguiente ejemplo muestra el uso de la condición (R)
, la cual comprueba
si la expresión ha sido evaluada dentro de una recursión:
pl@nereida:~/Lperltesting$ perl5.10.1 -wdE 0 main::(-e:1): 0 DB<1> x 'bbaaaabb' =~ /(b(?(R)a+|(?0))b)/ 0 'bbaaaabb' DB<2> x 'bb' =~ /(b(?(R)a+|(?0))b)/ empty array DB<3> x 'bab' =~ /(b(?(R)a+|(?0))b)/ empty array DB<4> x 'bbabb' =~ /(b(?(R)a+|(?0))b)/ 0 'bbabb'La sub-expresión regular
(?(R)a+|(?0))
dice:
si esta siendo evaluada recursivamente admite a+
si no, evalúa la regexp completa recursivamente.
Se trata en este ejercicio de generalizar la expresión
regular introducida en la sección
3.2.5
para reconocer los palabra-palíndromos3.7. Se trata de encontrar una regexp que acepte
que la lectura derecha e inversa de una frase en Español
pueda diferir en la acentuación (como es el caso
del clásico palíndromo dábale arroz a la zorra
el abad). Una solución trivial es preprocesar
la cadena eliminando los acentos. Supondremos sin embargo
que se quiere trabajar sobre la cadena original.
He aquí una solucion parcial (por
consideraciones de legibilidad sólo se consideran las vocales a
y o
:
1 pl@nereida:~/Lperltesting$ cat spanishpalin.pl 2 #!/usr/local/lib/perl/5.10.1/bin//perl5.10.1 -w -CIOEioA 3 use v5.10; 4 use strict; 5 use utf8; 6 7 my $regexp = qr/^(?<pal>\W* (?: 8 (?<L>(?<a>[áa])|(?<e>[ée])|\w) # letter 9 (?&pal) # nested palindrome 10 (?(<a>)[áa] # if is an "a" group 11 |(?:((?<e>)[ée] # if is an "e" group 12 |\g{L} # exact match 13 ) # end if [ée] 14 ) # end group 15 ) # end if [áa] 16 | \w? # non rec. case 17 ) \W* # punctuation symbols 18 ) 19 $ 20 /ix; 21 22 my $input = <>; # Try: 'dábale arroz a la zorra el abad'; 23 chomp($input); 24 if ($input =~ $regexp) { 25 say "$input is a palindrome"; 26 } 27 else { 28 say "$input does not match"; 29 }
Ejecución:
pl@nereida:~/Lperltesting$ ./spanishpalin.pl dábale arroz a la zorra el abad dábale arroz a la zorra el abad is a palindrome pl@nereida:~/Lperltesting$ ./spanishpalin.pl óuuo óuuo does not match pl@nereida:~/Lperltesting$ ./spanishpalin.pl éaáe éaáe is a palindrome
Hemos usado la opción -CIOEioA
para asegurarnos
que los ficheros de entrada/saldia y error y la línea de
comandos estan en modo UTF-8.
(Véase la sección )
Esto es lo que dice la documentación de perlrun al respecto:
The -C
flag controls some of the Perl Unicode features.
As of 5.8.1, the -C
can be followed either by a number or a list of option
letters. The letters, their numeric values, and effects are as follows;
listing the letters is equal to summing the numbers.
1 I 1 STDIN is assumed to be in UTF-8 2 O 2 STDOUT will be in UTF-8 3 E 4 STDERR will be in UTF-8 4 S 7 I + O + E 5 i 8 UTF-8 is the default PerlIO layer for input streams 6 o 16 UTF-8 is the default PerlIO layer for output streams 7 D 24 i + o 8 A 32 the @ARGV elements are expected to be strings encoded 9 in UTF-8 10 L 64 normally the "IOEioA" are unconditional, 11 the L makes them conditional on the locale environment 12 variables (the LC_ALL, LC_TYPE, and LANG, in the order 13 of decreasing precedence) -- if the variables indicate 14 UTF-8, then the selected "IOEioA" are in effect 15 a 256 Set ${^UTF8CACHE} to -1, to run the UTF-8 caching code in 16 debugging mode.
For example,-COE
and-C6
will both turn on UTF-8-ness on bothSTDOUT
andSTDERR
. Repeating letters is just redundant, not cumulative nor toggling.
The io options mean that any subsequentopen()
(or similar I/O operations) will have the:utf8
PerlIO layer implicitly applied to them, in other words,UTF-8
is expected from any input stream, andUTF-8
is produced to any output stream. This is just the default, with explicit layers inopen()
and withbinmode()
one can manipulate streams as usual.
-C
on its own (not followed by any number or option list), or the empty string""
for thePERL_UNICODE
environment variable, has the same effect as-CSDL
. In other words, the standard I/O handles and the defaultopen()
layer are UTF-8-fied but only if the locale environment variables indicate a UTF-8 locale. This behaviour follows the implicit (and problematic) UTF-8 behaviour of Perl 5.8.0.
You can use-C0
(or0
forPERL_UNICODE
) to explicitly disable all the above Unicode features.
El pragma use utf8
hace que se utilice una semántica de
carácteres (por ejemplo, la regexp /./
casará con un carácter unicode), el
pragma use bytes
cambia de semántica de caracteres
a semántica de bytes (la regexp .
casará con un byte).
lhp@nereida:~/Lperl/src/testing$ cat -n dot_utf8_2.pl 1 #!/usr/local/bin/perl -w 2 use strict; 3 use utf8; 4 use charnames qw{greek}; 5 6 binmode(STDOUT, ':utf8'); 7 8 my $x = 'αβγδεφ'; 9 10 my @w = $x =~ /(.)/g; 11 print "@w\n"; 12 13 { 14 use bytes; 15 my @v = map { ord } $x =~ /(.)/g; 16 print "@v\n"; 17 }Al ejcutar el programa obtenemos la salida:
pl@nereida:~/Lperltesting$ perl dot_utf8_2.pl
α β γ δ ε φ
206 177 206 178 206 179 206 180 206 181 207 134