NAME
perlop - Operadores y precedencia en Perl *** DOCUMENTO SIN REVISAR ***
DESCRIPCIÓN
En Perl, el operador determina qué operación se realiza, independiente del tipo de los operandos. Por ejemplo, $x + $y
siempre es una adición numérica, y si $x
o $y
no contienen números, se hace un intento para convertirles primero a números.
Esto contrasta con muchos otros lenguajes dinámicos, donde la operación se determina por el tipo del primer argumento. También significa que Perl tiene dos versiones de algunos operadores: uno para numérico y otro para cadenas de caracteres. Por ejemplo, $x == $y
compara dos números por su igualdad, y $x eq $y
comparas dos cadenas.
Aun así existen unas pocas excepciones: x
puede ser una repetición de cadenas o repetición de lista, dependiendo del tipo del operando de la izquierda, y &
, |
, ^
y ~
son operaciones de bit tanto numéricas como de cadena.
Precedencia de operadores y asociatividad
La precedencia de operadores y asociatividad funciona en Perl más o menos igual a como se hace en matemáticas.
Precedencia de operadores significa que algunos operadores se evalúan antes que otros. Por ejemplo, en 2 + 4 * 5
, la multiplicación tiene una precedencia mayor por lo que 4 * 5
se evalúa primero, resultando en 2 + 20 == 22
y no 6 * 5 == 30
.
Asociatividad de operadores define qué sucede si una secuencia de los mismos operadores se usa uno a continuación de otro: si el evaluador evaluará primero las operaciones a la izquierda o las de la derecha. Por ejemplo, en 8 - 4 - 2
, la resta es asociativa a la izquierda así que Perl evalúa la expresión de izquierda a derecha. 8 - 4
se evalúa primero dejando la expresión 4 - 2 == 2
y no 8 - 2 == 6
.
Los operadores Perl tienen la asociatividad y precedencia siguientes, enumerados de mayor a menor prioridad. Los operadores tomados del C mantienen la misma relación de precedencia entre sí, incluso donde la precedencia de C está ligeramente chiflada. (Esto hace el aprendizaje de Perl más fácil para la gente de C). Con pocas excepciones, todas éstas operan solamente en valores escalares, no en valores de array.
izquierda términos y operadores de lista (por la izquierda)
izquierda ->
no asoc. ++ --
derecha **
derecha ! ~ \ y los unarios + y -
izquierda =~ !~
izquierda * / % x
izquierda + - .
izquierda << >>
no asoc. operadores unarios nombrados
no asoc. < > <= >= lt gt le ge
no asoc. == != <=> eq ne cmp ~~
izquierda &
izquierda | ^
izquierda &&
izquierda || //
no asoc. .. ...
derecha ?:
right = += -= *= etc. goto last next redo dump
izquierda , =>
no asoc. operadores de lista (por la derecha)
derecha not
izquierda and
izquierda or xor
En las secciones siguientes, estos operadores están descritos en orden de precedencia.
Muchos operadores pueden ser sobrecargados por objetos. Ver sobrecarga.
Términos y operadores de lista (por la izquierda)
Un TÉRMINO tiene la mayor precedencia en Perl. Esto incluye a las variables, comillas y operadores de comillas, cualquier expresión entre paréntesis, y cualquier función cuyos argumentos estén entre paréntesis. En realidad, no son realmente funciones en ese sentido, solo son operadores de lista y operadores unarios que se comportan como funciones porque usted pone paréntesis a los argumentos. Están todas documentadas en perlfunc.
Si cualquier operador de lista (print()
, etc.) o cualquier operador unario (chdir()
, etc.) se sigue por un paréntesis de apertura como el siguiente token, el operador y los argumentos entre paréntesis se considera que son de mayor precedencia, como en una llamada a una función normal.
En ausencia de paréntesis, la precedencia de los operadores de lista como print
, sort
, o chmod
es, o muy alta o muy baja, dependiendo de si usted está mirando al lado izquierdo o al lado derecho del operador. Por ejemplo, en
@ary = (1, 3, sort 4, 2);
print @ary; # imprime 1324
las comas a la derecha de sort
se evalúan antes que el sort
, y las comas a la izquierda se evalúan después. En otras palabras, los operadores de lista tienden a devorar todos los argumentos que le siguen, y luego actúan como un único TÉRMINO con respecto a la expresión precedente. Tenga cuidado con los paréntesis:
# Evalúan exit antes de hacer el print:
print($foo, exit); # Obviamente, no es lo que quiere hacer.
print $foo, exit; # Tampoco esto.
# Esto llama al print antes de evaluar exit:
(print $foo), exit; # Esto es lo que quiere hacer.
print($foo), exit; # O esto.
print ($foo), exit; # O incluso esto.
También tenga en cuenta que
print ($foo & 255) + 1, "\n";
a primera vista, es probable que no sea lo que usted espera. Los paréntesis encierran la lista de argumentos para print
que se evalúa (imprimir el resultado de $foo & 255
). Entonces uno se añade al valor devuelto por print
(generalmente 1). El resultado es algo como esto:
1 + 1, "\n"; # Obviamente no es lo que quería decir.
Para hacer correctamente lo que quería decir, debe escribir:
print(($foo & 255) + 1, "\n");
Ver "Operadores unarios con nombre" para una discusión más sobre esto.
También se analizan como términos las construcciones do {}
y eval {}
, así como subrutina y llamadas a métodos, y los constructores anónimos []
y {}
.
Vea también "Comillas y operadores de comillas" hacia el final de esta sección, así como "Operadores E/S".
El operador flecha
"->
" es un operador infijo de desreferencia, tal como es en C y C++. Si el lado derecho es, o una [...]
, {...}
, o un subrango (...)
, entonces el lado izquierdo debe ser una referencia dura o simbólica a un array, un hash, o una subrutina, respectivamente. (O técnicamente hablando, un lugar capaz de contener una referencia dura, si se trata de una asignación de una referencia a un array o un hash). Vea perlreftut y perlref.
De lo contrario, el lado derecho es un nombre de método o una variable escalar simple conteniendo ya sea el nombre del método o una referencia a una subrutina, y el lado izquierdo debe ser un objeto (una referencia bendecida) o un nombre de clase (es decir, un nombre de paquete). Vea perlobj.
Los casos de desreferencia (opuestos a los casos de llamada a métodos) están un poco más extendidos por la característica postderef
. Para los detalles sobre esta característica, consulte "Sintaxis de desreferencia postfija" in perlref.
Auto incremento y auto decremento
"++"
y "--"
funcionan como en C. Es decir, si se colocan delante de una variable, incrementan o decrementan la variable en una unidad antes de devolver el valor; y colocados después, incrementan o decrementan después de haber devuelto el valor.
$i = 0; $j = 0;
print $i++; # imprime 0
print ++$j; # imprime 1
Tenga en cuenta que, al igual que en C, Perl no define cuándo la variable se incrementa o disminuye. Sólo sabe que se hará en algún momento antes o después de que el valor sea devuelto. Esto también significa que la modificación de una variable dos veces en la misma instrucción dará lugar a un comportamiento indefinido. Evite instrucciones como:
$i = $i ++;
print ++ $i + $i ++;
Perl no garantizará el resultado de las instrucciones anteriores.
El operador de auto incremento contiene un poco más de magia. Si usted incrementa una variable que es numérica, o que haya sido utilizada en un contexto numérico, se obtiene un incremento normal. Sin embargo, si la variable se ha utilizado sólo en contextos de cadena desde que se creó, y tiene un valor que no es la cadena vacía y coincide con el patrón /^[a-zA-Z]*[0-9]*\z/
, el incremento se realiza como una cadena, conservando cada carácter dentro de su rango, conllevando a:
print ++($foo = "99"); # imprime "100"
print ++($foo = "a0"); # imprime "a1"
print ++($foo = "Az"); # imprime "Ba"
print ++($foo = "zz"); # imprime "aaa"
undef
es tratado siempre como numérico, y, en particular, es cambiado a 0
antes de incrementar (de modo que un post-incremento de un valor undef devolverá 0
en lugar de undef
).
El operador de auto decremento no es mágico.
Exponenciación
Binario "**"
es el operador de exponenciación. Se une aún más estrechamente que la resta unaria, por lo que -2**4
es -(2**4)
, no (-2)**4
. (Esto se realiza mediante la función de C pow(3)
, que en realidad trabaja internamente con dobles).
Note que ciertas expresiones de exponenciación no están bien definidas: 0**0
, 1**Inf
, y Inf**0
. No espere ningún resultado en particular para estos casos especiales; los resultados son dependientes de la plataforma.
Operadores unarios simbólicos
El unario "!"
realiza la negación lógica, es decir, "not". Vea también not
para una versión de menor precedencia que ésta.
Unario "-"
lleva a cabo la negación aritmética si el operando es numérico, incluyendo cualquier cadena que se parezca a un número. Si el operando es un identificador, es devuelta una cadena formada por un signo menos concatenado con el identificador. De otra manera, si la cadena comienza con un signo más o un menos, se devuelve una cadena que comience con el signo opuesto. Uno de los efectos de estas reglas es que -palabra
es equivalente a la cadena "-palabra"
. Sin embargo, si la cadena comienza con un carácter no-alfabético (con exclusión de "+"
o "-"
), Perl tratará de convertir la cadena en un código numérico y se lleva a cabo la negación aritmética. Si la cadena no se puede convertir de una forma limpia a numérico, Perl mostrará la advertencia Argument "the string" isn't numeric in negation (-) at ....
Unario "~"
realiza la negación bit a bit, es decir, el complemento a uno. Por ejemplo, 0666 & ~027
es 0640. (Vea también "Aritmética entera" y "Operadores de bit en cadenas"). Tenga en cuenta que el ancho del resultado depende de la plataforma: ~0
es de 32 bits de ancho en una plataforma de 32 bits, pero 64 bits de ancho en una plataforma de 64 bits, así que si está esperando por un determinado ancho de bits, recuerde utilizar el operador "&"
para enmascarar los bits sobrantes.
Al complementar las cadenas, si todos los caracteres tienen valores ordinales menores de 256, sus complementarios, también lo serán. Pero si no lo son, todos los caracteres será complemento a 32- o 64-bit, dependiendo de su arquitectura. Así, por ejemplo, ~"\x{3B1}"
es "\x{FFFF_FC4E}"
en máquinas de 32 bits y "\x{FFFF_FFFF_FFFF_FC4E}"
en máquinas de 64 bits.
Si está activada la característica experimental "bitwise" por medio de use feature 'bitwise'
, entonces el unario "~"
siempre trata a sus argumentos como un número, y una forma alternativa del operador, "~."
, siempre trata a sus argumentos como una cadena. Así ~0
y ~"0"
devolverán 2**32-1 en plataformas de 32 bit, mientras que ~.0
y ~."0"
devolverán "\xff"
. Esta característica produce una advertencia a menos que use no warnings 'experimental::bitwise'
.
Unario "+"
no tiene efecto alguno, incluso en cadenas. Es útil para separar sintácticamente un nombre de función de una expresión entre paréntesis que, de otro modo, sería interpretada como la lista completa de argumentos de la función. (Ver ejemplos anteriores en "Términos y operadores de lista (por la izquierda)").
Unario "\"
crea una referencia a lo que sigue. Ver perlreftut y perlref. No se debe confundir este comportamiento con el comportamiento de una barra diagonal inversa en una cadena, aunque ambas formas transmiten la idea de proteger a lo que sigue, de ser interpolado.
Operadores de vinculación
El binario "=~"
une una expresión escalar a un patrón de coincidencia. Ciertas operaciones buscan o modifican la cadena $_
, por defecto. Este operador hace que este tipo de operación trabaje en alguna otra cadena. El argumento de la derecha es un patrón de búsqueda, sustitución o transliteración. El argumento de la izquierda es lo que se supone que debe ser registrado, sustituido o transcrito en lugar del predeterminado $_
. Cuando se usa en contexto escalar, el valor devuelto, por lo general, indica el éxito de la operación. Las excepciones son las sustituciones (s///
) y la transliteración (y///
) con la opción /r
(no destructiva), que hace regresar como valor, el resultado de la sustitución. El comportamiento en contexto de lista depende del propio operador. Vea "Operadores regex entrecomillados" para más detalles y perlretut para ejemplos usando estos operadores.
Si el argumento derecho es una expresión en lugar de un patrón de búsqueda, sustitución o transliteración, se interpreta como un patrón de búsqueda en tiempo de ejecución. Tenga en cuenta que esto significa que su contenido será interpolado dos veces.
'\\' =~ q'\\';
no es correcto, porque el motor de expresiones regulares acabará tratando de compilar el patrón \
, que lo considerará un error de sintaxis.
El binario "!~"
es justo como "=~"
excepto que se niega el valor de retorno, en el sentido lógico.
Un binario "!~"
con una sustitución no destructiva (s///r
) o transliteración (y///r
) es un error sintáctico.
Operadores multiplicativos
El binario "*"
multiplica dos números.
El binario "/"
divides dos números.
El binario "%"
es el operador módulo, que calcula el resto de la división de su primer argumento con respecto a su segundo argumento. Dados los operandos enteros $m
y $n
: si $n
es positivo, entonces $m % $n
es $m
menos el mayor múltiplo de $n
menor o igual a $m
. Si $n
es negativo, entonces $m % $n
es $m
menos el múltiplo más pequeño de $n
que no sea menor que $m
(es decir, el resultado será menor o igual a cero). Si los operandos $m
y $n
son valores en punto flotante y el valor absoluto de $n
(es decir, abs($n)
) es menor que (UV_MAX + 1)
, solo la porción de entero de $m
y $n
se usarán en la operación (Nota: aquí UV_MAX
significa el máximo valor del tipo entero sin signo). Si el valor absoluto del operando derecho (abs($n)
) es mayor o igual a (UV_MAX + 1)
, "%"
computa el resto en punto flotante $r
en la ecuación ($r = $m - $i*$n)
donde $i
es un cierto entero que hace que $r
tenga el mismo signo que el operando de la derecha $n
(no como el operando izquierdo $m
como en la función de C fmod()
) y el valor absoluto menor que el de $n
. Tenga en cuenta que cuando use integer
está activo en nuestro ámbito, "%"
da acceso directo al operador módulo, tal como está implementado por su compilador de C. Este operador no está tan bien definido para operandos negativos, pero se ejecutará más rápido.
El binario "x"
es el operador de repetición. En el contexto escalar o si el operando izquierdo no está encerrado entre paréntesis, devuelve una cadena consistente en el operando de la izquierda repetido el número de veces especificado por el operando de la derecha. En contexto de lista, si el operando de la izquierda se encierra entre paréntesis o es una lista formada por qw/CADENA/
, repite la lista. Si el operando derecho es cero o negativo (levantando una advertencia si es negativo), devuelve una cadena vacía o una lista vacía, dependiendo del contexto.
print '-' x 80; # imprime una fila de guiones
print "\t" x ($tab/8), ' ' x ($tab%8); # relleno con tabuladores
@unos = (1) x 80; # una lista de 80 unos
@unos = (5) x @unos; # pone todos los elementos a 5
Operadores aditivos
El binario "+"
devuelve la suma de dos números.
El binario "-"
devuelve la diferencia de dos números.
El binario "."
concatena dos cadenas.
Operadores de desplazamiento
El binario "<<"
devuelve el valor de su argumento de la izquierda, desplazado a la izquierda por el número de bits especificado por el argumento de la derecha. Los argumentos deben ser números enteros. (Vea también "Aritmética entera").
El binario ">>"
devuelve el valor de su argumento de la izquierda, desplazado a la derecha por el número de bits especificado por el argumento de la derecha. Los argumentos deben ser números enteros. (Vea también "Aritmética entera").
Si use integer
(vea "Aritmética entera") está en efecto entonces se usan los enteros de C con signo (desplazamiento aritmético), sino, se usan los enteros de C sin signo (desplazamiento lógico), incluso para los desplazamientos negativos. En el desplazamiento aritmético hacia la derecha, el signo de bit se replica a la izquierda, mientras que en el desplazamiento lógico los bits cero llegan por la izquierda.
De cualquier manera, la implementación no va a generar resultados más grandes que el tamaño del tipo entero con el que Perl fue compilado (32 o 64 bits).
Desplazar por un número negativo de bits significa el desplazamiento inverso: el desplazamiento izquierdo se convierte en derecho, y el derecho, en izquierdo. Esto es diferente que en C, donde el desplazamiento negativo no está definido.
Desplazar por más bits que el tamaño de los enteros significa cero en la mayor parte de los casos (todos los bits bajan), excepto cuando se está bajo use integer
sobredesplazar hacia la derecha un valor negativo resulta en -1. Esto es diferente que en C, donde el desplazamiento de demasiados bits no está definido. Un comportamiento común en C es "desplazamiento por un módulo del número de bits de una palabra", así que por ejemplo
1 >> 64 == 1 >> (64 % 64) == 1 >> 0 == 1 # Comportamiento común en C.
pero esto es completamente accidental.
Si se aburre de estar sujeto a los enteros de su plataforma, el pragma use bigint
elude claramente el tema por completo:
print 20 << 20; # 20971520
print 20 << 40; # 5120 en máquinas de 32 bit,
# 21990232555520 en máquinas de 64 bit
use bigint;
print 20 << 100; # 25353012004564588029934064107520
Operadores unarios con nombre
Los distintos operadores unarios con nombre se tratan como funciones con un argumento, con paréntesis opcionales.
Si cualquier operador de lista (print()
, etc.) o cualquier operador unario (chdir()
, etc.) se sigue por un paréntesis de apertura como el siguiente token, el operador y los argumentos entre paréntesis se considera que son de mayor precedencia, como en una llamada a una función normal. Por ejemplo, debido a que los operadores unarios, con nombre, tienen mayor precedencia que ||
:
chdir $foo || die; # (chdir $foo) || die
chdir($foo) || die; # (chdir $foo) || die
chdir ($foo) || die; # (chdir $foo) || die
chdir +($foo) || die; # (chdir $foo) || die
pero, debido a que "*"
es de mayor precedencia que los operadores con nombre:
chdir $foo * 20; # chdir ($foo * 20)
chdir($foo) * 20; # (chdir $foo) * 20
chdir ($foo) * 20; # (chdir $foo) * 20
chdir +($foo) * 20; # chdir ($foo * 20)
rand 10 * 20; # rand (10 * 20)
rand(10) * 20; # (rand 10) * 20
rand (10) * 20; # (rand 10) * 20
rand +(10) * 20; # rand (10 * 20)
En cuanto a la precedencia, los operadores de pruebas de archivos, como -f
, -M
, etc, se tratan como operadores unarios con nombre, pero no siguen esta regla funcional de los paréntesis. Esto significa, por ejemplo, que -f($archivo).".bak"
es equivalente a -f "$archivo.bak"
.
Vea también "Términos y operadores de lista (por la izquierda)".
Operadores relacionales
Los operadores de Perl que devuelven verdadero o falso, en general, devuelven valores que pueden ser usados, con seguridad, como números. Por ejemplo, los operadores relacionales en esta sección y los operadores de igualdad en la siguiente devuelven 1
para verdadero y una versión especial de la cadena definida vacía, ""
, que cuenta como un cero, pero está exenta de advertencias acerca de conversiones numéricas impropias, como lo está "0 pero verdadero"
.
El binario "<"
devuelve verdadero si el argumento de la izquierda es numéricamente menor que el argumento de la derecha.
El binario ">"
devuelve verdadero si el argumento de la izquierda es numéricamente mayor que el argumento de la derecha.
El binario "<="
devuelve verdadero si el argumento de la izquierda es numéricamente menor o igual que el argumento de la derecha.
El binario ">="
devuelve verdadero si el argumento de la izquierda es numéricamente mayor o igual que el argumento de la derecha.
El binario "lt"
devuelve verdadero si el argumento de la izquierda es alfanuméricamente menor que el argumento de la derecha.
El binario "gt"
devuelve verdadero si el argumento de la izquierda es alfanuméricamente mayor que el argumento de la derecha.
El binario "le"
devuelve verdadero si el argumento de la izquierda es alfanuméricamente menor o igual que el argumento de la derecha.
El binario "ge"
devuelve verdadero si el argumento de la izquierda es alfanuméricamente mayor o igual que el argumento de la derecha.
Operadores de igualdad
El binario "=="
devuelve verdadero si el argumento de la izquierda es numéricamente igual que el argumento de la derecha.
El binario "!="
devuelve verdadero si el argumento de la izquierda es numéricamente distinto que el argumento de la derecha.
El binario "<=>"
devuelve -1, 0 o 1 dependiendo de si el argumento de la izquierda es numéricamente menor, igual o mayor que el argumento de la derecha. Si su plataforma soporta NaN
(not-a-numbers, no-es-un-número) como valores numéricos, usándolos con "<=>"
devuelve undef. NaN no es "<", "==", ">", "<=" o ">=" ni cualquier otra cosa (incluso NaN), así que estos 5 devuelven falso. NaN != NaN
devuelve verdadero, como con NaN !=
con cualquier otra cosa. Si su plataforma no soporta NaN
entonces NaN
solo es una cadena con un valor numérico 0.
$ perl -le '$x = "NaN"; print "No hay soporte para NaN" if $x == $x'
$ perl -le '$x = "NaN"; print "No hay soporte para NaN" if $x != $x'
(Tenga en cuenta que los pragmas bigint, bigrat y bignum soportan "NaN"
).
El binario "eq"
devuelve verdadero si el argumento de la izquierda es alfanuméricamente igual que el argumento de la derecha.
El binario "ne"
devuelve verdadero si el argumento de la izquierda es alfanuméricamente distinto que el argumento de la derecha.
El binario "cmp"
devuelve -1, 0 o -1 dependiendo de si el argumento de la izquierda es alfanuméricamente menor, igual o mayor que el argumento de la derecha.
El binario "~~"
hace una coincidencia inteligente entre sus argumentos. La Coincidencia inteligente se describe en la sección siguiente.
"lt"
, "le"
, "ge"
, "gt"
y "cmp"
usan el orden de cotejo (sort) especificado por la configuración regional actual LC_COLLATE
si está en vigor una forma de use locale
que incluya cotejo. Vea perllocale. No los mezcle con Unicode, úselos solo con antiguas codificaciones regionales de 8 bits. Los módulos estándares Unicode::Collate
y Unicode::Collate::Locale
ofrecen soluciones mucho más poderosas a los problemas de cotejamiento.
Para comparaciones insensibles al tamaño de caja, mire la función de plegado de tamaño de caja "fc" in perlfunc, disponible a partir de Perl v5.16:
if ( fc($x) eq fc($y) ) { ... }
Operador Coincidencia inteligente
Disponible por primera vez en Perl 5.10.1 (la versión 5.10.0 se comportaba de manera diferente), el binario ~~
hace una "coincidencia inteligente" entre sus argumentos. Casi siempre se usa implícitamente en la construcción when
descrito en perlsyn, aunque no todas las cláusulas when
llaman al operador coincidencia inteligente. Único entre todos los operadores de Perl, el operador coincidencia inteligente puede ser recursivo. El operador coincidencia inteligente es experimental y su comportamiento está sujeto a cambio.
También es único en que todos los demás operadores de Perl imponen un contexto (generalmente contexto numérico o de cadena) en sus operandos, autoconvirtiendo estos operandos a esos contextos impuestos. En contraste, la coincidencia inteligente infiere el contexto a partir de los tipos reales de sus operandos, y usa esta información para seleccionar un mecanismo de comparación adecuado.
El operador ~~
compara sus operandos de forma "polimórfica", determinando cómo compararlos en función de sus tipos reales (numérico, cadena, array, hash, etc.). Al igual que los operadores de igualdad con los que comparte la misma precedencia, ~~
devuelve 1 para verdadero y ""
para falso. A menudo es mejor leerlo en voz alta como "en", "dentro de", o "está contenido en", ya que a menudo el operando de la izquierda es visto como dentro del operando derecho. Esto hace que el orden de los operandos del operador coincidencia inteligente a menudo es opuesto a la del operador expresión regular. En otras palabras, la cosa más "pequeña" se suele colocar en el operando de la izquierda y el más grande en el de la derecha.
El comportamiento del operador coincidencia inteligente depende del tipo de sus argumentos, según lo determinado por la siguiente tabla. La primera fila de la tabla cuyos tipos coincidan determina el comportamiento de coincidencia inteligente. Debido a que lo que realmente sucede es determinado principalmente por el tipo del segundo operando, la tabla está ordenada alfabéticamente por el operando de la derecha en vez de por el de la izquierda.
Izquierdo Derecho Descripción y pseudocódigo
===============================================================
Cualquiera undef comprueba cuándo Cualquiera es indefinido
igual que: !defined Cualquiera
Cualquiera Objeto invoca ~~ sobrecargado en Objeto, o muere
Operando derecho es un ARRAY:
Izquierdo Derecho Descripción y pseudocódigo
===============================================================
ARRAY1 ARRAY2 repite acción en cada par de elementos de ARRAY1 y ARRAY2[2]
igual que: (ARRAY1[0] ~~ ARRAY2[0])
&& (ARRAY1[1] ~~ ARRAY2[1]) && ...
HASH ARRAY cualquier elemento de ARRAY que exista como clave de HASH
igual que: grep { exists HASH->{$_} } ARRAY
Regex ARRAY cualquier elemento de ARRAY que coincida con el patrón Regex
igual que: grep { /Regex/ } ARRAY
undef ARRAY undef en el ARRAY
igual que: grep { !defined } ARRAY
Cualquier ARRAY coincidencia inteligente en cada elemento de ARRAY[3]
igual que: grep { Cualquiera ~~ $_ } ARRAY
Operando derecho es un HASH:
Izquierdo Derecho Descripción y pseudocódigo
===============================================================
HASH1 HASH2 las mismas claves en ambos HASHes
igual que: keys HASH1 ==
grep { exists HASH2->{$_} } keys HASH1
HASH ARRAY cualquier elemento de ARRAY que exista como clave de HASH
igual que: grep { exists HASH->{$_} } ARRAY
Regexp HASH cualquier clave del HASH que coincida con el patrón Regexp
igual que: grep { /Regex/ } keys HASH
undef HASH siempre falso (undef no puede ser una clave)
igual que: 0 == 1
Cualquiera HASH existencia de una clave HASH
igual que: exists HASH->{Cualquiera}
Operando derecho es CÓDIGO:
Izquierdo Derecho Descripción y pseudocódigo
===============================================================
ARRAY CÓDIGO sub devuelve verdadero en todos los elementos de ARRAY[1]
igual que: !grep { !CÓDIGO->($_) } ARRAY
HASH CÓDIGO sub devuelve verdadero en todas las claves del HASH[1]
igual que: !grep { !CÓDIGO->($_) } keys HASH
Cualquiera CÓDIGO a sub se le pasa Cualquiera y devuelve verdadero
igual que: CÓDIGO->(Cualquiera)
Operando derecho es una Regex:
Izquierdo Derecho Descripción y pseudocódigo
===============================================================
ARRAY Regex cualquier elemento de ARRAY que coincida con Regex
igual que: grep { /Regex/ } ARRAY
HASH Regex cualquier clave de HASH que coincida con Regex
igual que: grep { /Regex/ } keys HASH
Cualquiera Regex coincidencia
igual que: Cualquiera =~ /Regex/
Otro:
Izquierdo Derecho Descripción y pseudocódigo
===============================================================
Objeto Cualquiera invoca ~~ sobrecargado en el Objeto,
o si no...
Cualquiera Número igualdad numérica
igual que: Cualquiera == Número
Cualquiera Número[4] igualdad numérica
igual que: Número == es_como_un_número
undef Cualquiera comprueba cuándo es indefinido
igual que: !defined(Cualquiera)
Cualquiera Cualquiera igualdad de cadena
igual que: Cualquiera eq Cualquiera
Notas:
- 1. Hash o array vacíos coinciden.
- 2. Es decir, cada elemento coincide inteligentemente con el elemento del mismo índice del otro array.[3]
- 3. Si se encuentra una referencia circular, regresamos a la igualdad referencial.
- 4. O un número real, o una cadena que se parezca a un número.
La coincidencia inteligente desreferencia implícitamente cualquier referencia hash o array, por lo que en esos casos se aplica a las entradas HASH
y ARRAY
. Para las referencias bendecidas, se aplica a las entradas Objeto
. Las coincidencias inteligentes que involucran a hashes sólo tienen en cuenta a las claves del hash, nunca a los valores del hash.
El ejemplo de código indicado con "igual que", no siempre es una interpretación exacta de lo que ocurre. Por ejemplo, el operador de coincidencia inteligente cortocircuita cuando sea posible, pero grep
no lo hace. Además, grep
en contexto de escalar devuelve el número de coincidencias, pero ~~
sólo devuelve verdadero o falso.
A diferencia de la mayoría de los operadores, el operador coincidencia inteligente sabe tratar a undef
de forma especial:
use v5.10.1;
@array = (1, 2, 3, undef, 4, 5);
say "algunos elementos indefinidos" if undef ~~ @array;
Cada operando es considerado en un contexto de escalar modificado, siendo esa modificación que las variables array y hash son pasadas por referencia al operador, lo que implícitamente los referencia. Lo mismo para cada par de elementos:
use v5.10.1;
my %hash = (rojo => 1, azul => 2, verde => 3,
naranja => 4, amarillo => 5, purpura => 6,
negro => 7, gris => 8, blanco => 9);
my @array = qw(rojo azul verde);
say "algunos elementos del array son claves del hash" if @array ~~ %hash;
say "algunos elementos del array son claves del hash" if \@array ~~ \%hash;
say "rojo en array" if "rojo" ~~ @array;
say "rojo en array" if "rojo" ~~ \@array;
say "algunas claves acaban en e" if /e$/ ~~ %hash;
say "algunas claves acaban en e" if /e$/ ~~ \%hash;
Dos array coinciden inteligentemente si cada elemento del primer array coincide inteligentemente (es decir, está "en") el correspondiente elemento del segundo array, de forma recursiva.
use v5.10.1;
my @pequeno = qw(rojo azul verde);
my @grande = ("rojo", "azul", [ "naranja", "verde" ] );
if (@pequeno ~~ @grande) { # ¡verdadero!
say "pequeño está contenido en grande";
}
Debido a que el operador coincidencia inteligente aplica de forma recursiva en los arrays anidados, seguirá informando de que "rojo" está en el array.
use v5.10.1;
my @array = qw(rojo azul verde);
my $array_anidado = [[[[[[[ @array ]]]]]]];
say "rojo en array" if "rojo" ~~ $array_anidado;
Si dos arrays coinciden inteligentemente uno con el otro, entonces son copias en profundidad de cada uno de los valores de cada uno, como muestra este ejemplo:
use v5.12.0;
my @a = (0, 1, 2, [3, [4, 5], 6], 7);
my @b = (0, 1, 2, [3, [4, 5], 6], 7);
if (@a ~~ @b && @b ~~ @a) {
say "a y b son copias en profundidad uno del otro";
}
elsif (@a ~~ @b) {
say "a coincide inteligentemente en b";
}
elsif (@b ~~ @a) {
say "b coincide inteligentemente en a";
}
else {
say "a y b no coinciden inteligentemente uno con el otro";
}
Si se hace $b[3] = 4
, entonces, en vez de informar que "a y b son copias en profundidad una del otro", ahora informa que "b coincide inteligentemente en a"
. Eso es así porque la correspondiente posición en @a
contiene un array que (eventualmente) contiene un 4.
Coincidencia inteligente de un hash contra otro informa que ambos contienen las mismas claves, ni más ni menos. Esto podría ser utilizado para determinar si dos registros tienen los mismos nombres de campo, sin importar qué valores puedan ser estos campos. Por ejemplo:
use v5.10.1;
sub make_dogtag {
state $CAMPOS_REQUERIDOS = { nombre=>1, rango=>1, num_serie=>1 };
my ($clase, $inic_campos) = @_;
die "Debe indicar (solamente el) nombre, rango, y número de serie"
unless $inic_campos ~~ $CAMPOS_REQUERIDOS;
...
}
Sin embargo, esto solo hace lo que usted indica si $inic_campos
es verdaderamente una referencia hash. La condición $inic_campos ~~ $CAMPOS_REQUERIDOS
también permite las cadenas "nombre"
, "rango"
, "num_serie"
así como cualquier referencia de array que contiene "nombre"
o "rango"
o "num_serie"
en cualquier parte que se les pase.
El operador coincidencia inteligente se utiliza más como el operador implícito en una cláusula when
. Vea la sección "Instrucciones Switch" en perlsyn.
Coincidencia inteligente de objetos
Para evitar depender de la representación subyacente de un objeto, si el operador de la derecha de una coincidencia inteligente es un objeto que no sobrecarga ~~
, lanza la excepción "Smartmatching a non-overloaded object breaks encapsulation
" (Coincidencia inteligente de un objeto no sobrecargado rompe la encapsulación). Eso es porque no tiene sentido cavar alrededor para ver si algo está "dentro de" un objeto. Todos los siguientes son ilegales sobre objetos sin un ~~
sobrecargado:
%hash ~~ $objeto
42 ~~ $objeto
"pedro" ~~ $objeto
Sin embargo, puede cambiar la forma en que un objeto es comparado inteligentemente sobrecargando el operador ~~
. Se permite extender la semántica habitual de la coincidencia inteligente. Para los objetos que tienen un ~~
sobrecargado, vea overload.
Está permitido el uso de un objeto como operando de la izquierda, aunque no es muy útil. Las reglas de la Coincidencia inteligente tienen prioridad sobre la sobrecarga, por lo que incluso si el objeto en el operando de la izquierda tiene una sobrecarga de la coincidencia inteligente, ésta será ignorada. Un operando de la izquierda que es un objeto no sobrecargado es transformado en una comparación de cadena o numérica de lo que el operador ref
devuelva. Esto significa que
$objeto ~~ X
no invoca el método sobrecargado con X
como argumento. En lugar de eso, se consulta la tabla anterior de forma normal, y en función del tipo de X
, la sobrecarga puede ser o no invocada. Para cadenas simples o números, "se" convierte en el equivalente a esto:
$objeto ~~ $numero ref($objeto) == $numero
$objeto ~~ $cadena ref($objeto) eq $cadena
Por ejemplo, lo siguiente informa que el identificador huele a IO (pero, por favor, ¡no haga esto!):
use IO::Handle;
my $fh = IO::Handle->new();
if ($fh ~~ /\bIO\b/) {
say "el identificador huele a IO";
}
Esto se debe a que trata $fh
como una cadena como "IO::Handle=glob(0x8039e0)"
, que es contra lo que el patrón coincidirá.
And binario
El binario "&"
devuelve la operación AND, bit a bit, de sus operandos. A pesar de que no se levante en este momento ninguna advertencia, el resultado no está bien definido cuando esta operación actúa en operandos que no son ni números (vea "Aritmética entera") ni cadenas de bits (vea "Operadores de bit en cadenas").
Tenga en cuenta que "&"
tiene una menor prioridad que los operadores relacionales, así que, por ejemplo, los paréntesis son esenciales en una prueba como
print "Par\n" if ($x & 1) == 0;
Si está activada la característica experimental "bitwise" por medio de use feature 'bitwise'
, entonces este operador siempre trata a sus argumentos como números. Esta característica produce una advertencia a menos que también use no warnings 'experimental::bitwise'
.
Or y exclusivo or binarios
El binario "|"
devuelve la operación OR, bit a bit, de sus operandos.
El binario "^"
devuelve la operación XOR, bit a bit, de sus operandos.
A pesar de que no se levante en este momento ninguna advertencia, los resultados no están bien definidos cuando esta operación actúa en operandos que no son ni números (vea "Aritmética entera") ni cadenas de bits (vea "Operadores de bit en cadenas").
Tenga en cuenta que "|"
y "^"
tienen menor prioridad que los operadores relacionales, así que, por ejemplo, los paréntesis son esenciales en una prueba como
print "falso\n" if (8 | 2) != 10;
Si está activada la característica experimental "bitwise" por medio de use feature 'bitwise'
, entonces este operador siempre trata a sus argumentos como números. Esta característica produce una advertencia a menos que use no warnings 'experimental::bitwise'
.
And lógico al estilo del C
El binario "&&"
realiza una operación lógica AND abreviada. Es decir, si el operando izquierdo es falso, el operando de la derecha no es ni siquiera evaluado. Los contextos escalar o lista se propagan hacia el operando de la derecha si éste es evaluado.
Or lógico al estilo del C
El binario "||"
realiza una operación lógica OR abreviada. Es decir, si el operando izquierdo es verdadero, el operando de la derecha no es ni siquiera evaluado. Los contextos escalar o lista se propagan hacia el operando de la derecha si éste es evaluado.
Defined-Or lógico
A pesar de que no tiene equivalente directo en C, el operador Perl //
está relacionado con el operador "or" del C. De hecho, es exactamente lo mismo que ||
, excepto que comprueba la definición del lado izquierdo en lugar de su estado de verdad. Por lo tanto, EXPR1 // EXPR2
devuelve el valor de EXPR1
si está definida, de lo contrario, se devuelve el valor de EXPR2
. (EXPR1
se evalúa en contexto de escalar, EXPR2
en el propio contexto de //
). Normalmente, este es el mismo resultado que defined(EXPR1) ? EXPR1 : EXPR2
(salvo que la forma del operador ternario se puede utilizar como un valor-izquierda, mientras que EXPR1 // EXPR2
, no). Esto es muy útil para proporcionar valores por defecto a las variables. Si realmente desea probar si al menos uno de los dos, $x
o $y
, están definidos, use defined($x // $y)
.
Los operadores ||
, //
y &&
devuelven el último valor evaluado (a diferencia de los operadores del C ||
y &&
, que devuelve 0 o 1). Por lo tanto, un forma razonablemente portátil para averiguar nuestro directorio principal podría ser:
$home = $ENV{HOME}
// $ENV{LOGDIR}
// (getpwuid($<))[7]
// die "¡Eres un sintecho!\n";
En particular, esto significa que usted no debería usar esto para seleccionar entre dos agregados para hacer una asignación:
@a = @b || @c; # Esto no hace lo correcto
@a = scalar(@b) || @c; # porque realmente quiere decir esto.
@a = @b ? @b : @c; # Aunque esto también funciona.
Como alternativas a &&
y ||
cuando se usan para control de flujo, Perl proporciona los operadores and
y or
(vea más adelante). El comportamiento abreviado es idéntico. Sin embargo, la precedencia de "and"
y "or"
es mucho menor, de modo que puede usarlos con seguridad después de un operador de lista sin necesidad de poner paréntesis:
unlink "alfa", "beta", "gamma"
or gripe(), next LINEA;
Con los operadores del estilo del C esto se hubiera escrito así:
unlink("alfa", "beta", "gamma")
|| (gripe(), next LINEA);
Sería incluso más claro escribirlo de esta manera:
unless(unlink("alfa", "beta", "gama")) {
gripe();
next LINEA;
}
Es poco probable que quiera usar "or"
para hacer asignaciones; vea más abajo.
Operadores de rango
El binario ".."
es el operador rango, que en realidad son dos operadores diferentes dependiente del contexto. En contexto de lista, devuelve una lista de valores contando (de uno en uno) desde el valor de la izquierda al valor de la derecha. Si el valor de la izquierda es mayor que el valor de la derecha entonces devuelve la lista vacía. El operador rango es útil para escribir bucles foreach (1..10)
y para hacer operaciones de troceado en los arrays. En la implementación actual, no se crea ningún array temporal cuando el operador rango es usado como expresión en los bucles foreach
, pero versiones anteriores de Perl pueden quemar una gran cantidad de memoria cuando se escribe algo como esto:
for (1 .. 1_000_000) {
# código
}
El operador rango también trabaja en las cadenas, usando el auto-incremento mágico. Vea más abajo.
En contexto de escalar, ".."
devuelve un valor booleano. El operador es biestable, como un flip-flop, y emula el operador rango-de-línea de sed, awk, y diversos editores. Cada operador ".."
mantiene su estado booleano propio, incluso a través de llamadas a la subrutina que lo contenga. Es falso, siempre y cuando su operando izquierdo sea falso. Una vez que el operando izquierdo sea verdadero, el operador rango se mantiene así hasta que el operando de la derecha sea verdadero, DESPUÉS de lo cual, el operador rango se vuelve falso de nuevo. No se vuelve falso hasta la próxima vez que el operador rango es evaluado. El operador rango puede probar el operando de la derecha y convertirse en falso en la misma evaluación en que se hizo verdadero (como en awk), pero aún así devuelve verdadero al menos una vez. Si no quiere poner a prueba el operando derecho hasta la próxima evaluación, al igual que en sed, sólo tiene que utilizar tres puntos ("..."
) en lugar de dos. En todos los demás aspectos, "..."
se comporta como ".."
.
El operando de la derecha no es evaluado mientras que el operador esté en el estado "falso", y el operando de la izquierda no es evaluado mientras que el operador se encuentre en el estado "verdadero". La precedencia es un poco menor que || y &&. El valor devuelto es una cadena vacía para falso, o un número de secuencia (empezando por 1) para verdadero. El número de secuencia se reinicia para cada rango encontrado. El número de secuencia final en un rango tiene la cadena "E0" añadida, que no afecta a su valor numérico, pero le da un apoyo para poder buscarlo si desea excluir el punto final de la secuencia. Puede excluir el punto de partida esperando por un número de secuencia mayor que 1.
Si alguno de los operandos del escalar ".."
es una expresión constante, ese operando se considera cierto si es igual (==
) al número de línea actual de la entrada (la variable $.
).
Para ser un poco más pedante, la comparación es en realidad int(EXPR) == int(EXPR)
, pero esto sólo es un problema si utiliza una expresión de punto flotante; cuando, implícitamente, está usando $.
como se describe en el párrafo anterior, la comparación es int(EXPR) == int($.)
que sólo es un problema cuando $.
se establece en un valor de punto flotante y usted no está leyendo desde un archivo. Por otra parte, "span" .. "spat"
o 2.18 .. 3,14
no harán lo que quiere que hagan en contexto escalar porque cada uno de los operandos se evalúan utilizando su representación entera.
Ejemplos:
Como operador escalar:
if (101 .. 200) { print; } # imprime las segundas cien líneas, versión corta de
# if ($. == 101 .. $. == 200) { print; }
next LINEA if (1 .. /^$/); # salta las líneas de cabecera, resumen de
# next LINEA if ($. == 1 .. /^$/);
# (típicamente en un bucle etiquetado con LINEA)
s/^/> / if (/^$/ .. eof()); # citar el cuerpo
# analizar mensajes de correo
while (<>) {
$en_cabecera = 1 .. /^$/;
$en_cuerpo = /^$/ .. eof;
if ($en_cabecera) {
# hacer algo
} else { # en cuerpo
# hacer sino otra cosa
}
} continue {
close ARGV if eof; # reinicia $. por cada archivo
}
He aquí un ejemplo sencillo para ilustrar la diferencia entre los dos operadores rango:
@lineas = (" - Foo",
"01 - Bar",
"1 - Baz",
" - Quux");
foreach (@lineas) {
if (/0/ .. /1/) {
print "$_\n";
}
}
Este programa imprimirá sólo la línea que contiene "Bar". Si el operador se cambia a ...
, también se imprimirá la línea "Baz".
Y ahora algunos ejemplos como un operador de lista:
for (101 .. 200) { print } # imprime $_ 100 veces
@foo = @foo[0 .. $#foo]; # una costosa no-operación
@foo = @foo[$#foo-4 .. $#foo]; # trocea los últimos 5 elementos
El operador rango (en contexto de lista) hace uso del algoritmo auto-incremental mágico, si los operandos son cadenas. Se puede decir
@alfabeto = ("A" .. "Z");
Para obtener todas las letras normales del alfabeto Inglés, o
$hexdigito = (0 .. 9, "a" .. "f")[$numero & 15];
para obtener un dígito hexadecimal o
@z2 = ("01" .. "31");
print $z2[$mday];
para obtener fechas con ceros a la izquierda.
Si el valor final especificado no está en la secuencia que el incremento mágico produciría, la secuencia continúa hasta el siguiente valor que sería más largo que el valor final fijado.
Si el valor inicial especificado no es parte de una secuencia mágica de incremento (es decir, una cadena no vacía coincidente con /^[a-zA-Z]*[0-9]*\z/
), sólo se devolverá el valor inicial. Así que lo siguiente sólo devolverá un alfa:
use charnames "greek";
my @griegas_minusculas = ("\N{alpha}" .. "\N{omega}");
Para obtener las 25 letras minúsculas griegas, incluyendo ambos sigmas, puede usar esto:
use charnames "greek";
my @griegas_minusculas = map { chr } ( ord("\N{alpha}")
..
ord("\N{omega}")
);
Sin embargo, debido a que existen muchos otros caracteres griegos en minúscula aparte de estos, para buscar por caracteres griegos en minúscula en una expresión regular, podría utilizar el patrón /(?:(?=\p{Greek})\p{Lower})+/
(o la característica experimental /(?[ \p{Greek} & \p{Lower} ])+/
).
Debido a que cada operando se evalúa en forma de número entero, 2.18 .. 3.14
devolverá dos elementos en el contexto lista.
@lista = (2.18 .. 3.14); # lo mismo que @lista = (2 .. 3);
Operadores condicionales
El ternario "?:"
es el operador condicional, al igual que en C. Funciona como un if-then-else. Si el argumento anterior al ?
es verdadero, se devuelve el argumento anterior al :
; de lo contrario se devuelve el argumento posterior a :
. Por ejemplo:
printf "Tengo %d perro%s.\n", $n,
($n == 1) ? "" : "s";
Contexto escalar o lista es propagado hacia adelante, en el segundo o tercer argumento, cualquiera que sea el seleccionado.
$x = $ok ? $y : $z; # obtiene un escalar
@x = $ok ? @y : @z; # obtiene un array
$x = $ok ? @y : @z; # oops, ¡esto solo cuenta elementos!
El operador puede ser asignado si tanto el segundo y tercer argumentos son valores-izquierda legales (lo que significa que se les puede asignar valores):
($x_or_y ? $x : $y) = $z;
Debido a que este operador produce un resultado asignable, usar asignaciones sin paréntesis hará que se meta en problemas. Por ejemplo, esto:
$x % 2 ? $x += 10 : $x += 2
En realidad significa lo siguiente:
(($x % 2) ? ($x += 10) : $x) += 2
En lugar de esto:
($x % 2) ? ($x += 10) : ($x += 2)
Esto, probablemente, se debe escribir más sencillamente como:
$x += ($x % 2) ? 10 : 2;
Operadores de asignación
"="
es el operador ordinario de asignación.
Los operadores de asignación funcionan como en C. Es decir,
$x += 2;
es equivalente a
$x = $x + 2;
pero sin duplicar los efectos colaterales que, desreferenciando el valor-izquierda, se podrían desencadenar, como por ejemplo, de tie()
. Otros operadores de asignación funcionan de manera similar. Lo siguiente es reconocido como correcto:
**= += *= &= &.= <<= &&=
-= /= |= |.= >>= ||=
.= %= ^= ^.= //=
x=
Aunque estos están agrupados por familia, todos ellos tienen la precedencia de la asignación. Estos operadores de asignación combinados solo pueden operar en escalares, mientras que el operador de asignación ordinario puede asignar a arrays, hashes, listas e incluso referencias. (Vea "Contexto" y "Constructores de valores de lista" in perldata, y "Asignar a referencias" in perlref).
A diferencia de C, el operador de asignación escalar produce un valor-izquierda válido. Modificar una asignación es equivalente a realizar la asignación y luego modificar la variable que le fue asignada. Esto es útil para modificar una copia de algo, como esto:
($tmp = $global) =~ tr/13579/24680/;
A partir de 5,14, también puede llevarse a cabo de esta manera:
use v5.14;
$tmp = ($global =~ tr/13579/24680/r);
Del mismo modo,
($x += 2) *= 3;
es equivalente a
$x += 2;
$x *= 3;
Del mismo modo, una asignación de lista en contexto de lista produce la lista de valores-izquierda asignados, y una asignación de lista en contexto escalar devuelve el número de elementos producidos por la expresión en el lado derecho de la asignación.
Los operadores de asignación binarios con punto (&.=
|.=
^.=
) son nuevos en Perl 5.22 y experimentales. Vea "Operadores de bit en cadenas".
Operador coma
El binario ","
es el operador coma. En contexto escalar evalúa su argumento de la izquierda, descarta este valor, y luego evalúa su argumento de la derecha y devuelve este valor. Es igual que el operador coma del C.
En contexto lista, es solo el separador de la lista de argumentos, e inserta sus argumentos en la lista. Estos argumentos también son evaluados de izquierda a derecha.
El operador =>
(algunas veces llamado "coma gorda") es un sinónimo de la coma, salvo que causa que su operando de la izquierda deba interpretarse como una cadena si comienza con una letra o un guión bajo, y está exclusivamente integrado por letras, dígitos y guiones bajos. Esto incluye operandos que, de lo contrario, podrían interpretarse como operadores, constantes, un solo número o v-cadenas o llamadas a funciones. En caso de duda acerca de este comportamiento, el operando de la izquierda puede ser entrecomillado de forma explícita.
De lo contrario, el operador =>
se comporta exactamente como el operador coma o separador de lista de argumentos, según el contexto.
Por ejemplo:
use constant FOO => "algo";
my %h = ( FOO => 23 );
es equivalente a:
my %h = ("FOO", 23);
NO es:
my %h = ("algo", 23);
El operador =>
es útil para documentar la correspondencia entre claves y valores de hashes, y otros elementos vinculados en listas.
%hash = ( $clave => $valor );
login( $usuario => $contraseña );
Este comportamiento especial de entrecomillado ignora la precedencia, y por lo tanto puede aplicarse a parte del operando de la izquierda:
print time.shift => "bbb";
Este ejemplo imprime algo así como "1314363215shiftbbb"
, ya que el =>
implícitamente entrecomilla el shift
inmediatamente a su izquierda, ignorando el hecho de que time.shift
es el operador completo de la izquierda.
Operadores de lista (por la derecha)
En el lado derecho de un operador de lista, la coma tiene una precedencia muy baja, de forma que controla todas las expresiones separadas por comas que se encuentren allí. Los únicos operadores con menor precedencia son los operadores lógicos "and"
, "or"
, y "not"
, que se pueden utilizar para evaluar las llamadas a los operadores de lista sin necesidad de paréntesis:
open HANDLE, "< :utf8", "archivo" or die "No puedo abrir: $!\n";
Sin embargo, algunas personas encuentran este código más difícil de leer que escribiéndolo con paréntesis:
open(HANDLE, "< :utf8", "archivo") or die "No puedo abrir: $!\n";
en cuyo caso puede también acabar utilizando el operador más habitual "||"
:
open(HANDLE, "< :utf8", "archivo") || die "No puedo abrir: $!\n";
Vea también la discusión de los Operadores de lista en "Términos y operadores de lista (por la izquierda)".
Not lógico
El unario "not"
devuelve la negación lógica de la expresión a su derecha. Es el equivalente de "!"
excepto por tener una precedencia muy baja.
And lógico
El binario "and"
devuelve la conjunción lógica de las dos expresiones que la rodean. Es equivalente a "&&" excepto por tener una precedencia muy baja. Esto significa que cortocircuita: es decir, la expresión de la derecha sólo se evalúa si la expresión de la izquierda es verdadera.
Or lógico y Or exclusivo
El binario "or"
devuelve la disyunción lógica de las dos expresiones que la rodean. Es equivalente a "||" excepto por tener una precedencia muy baja. Esto lo hace útil para el control de flujo:
print FH $dato or die "No puedo escribir a FH: $!";
Esto significa que cortocircuita: es decir, la expresión de la derecha sólo se evalúa si la expresión de la izquierda es falsa. Debido a su precedencia, debería evitar el uso de este operador como un reemplazo del operador ||
. Por lo general, funciona mejor para el control flujo que en las asignaciones:
$x = $y or $z; # error: esto está mal
($x = $y) or $z; # realmente quiere decir esto
$x = $y || $z; # mejor escrito así
Sin embargo, cuando se trata de una asignación en contexto de lista y está tratando de usar ||
para el control de flujo, es probable que necesite usar "or"
para que la asignación tenga la mayor precedencia.
@info = stat($archivo) || die; # ¡oops, sentido escalar de stat!
@info = stat($archivo) or die; # mejor, ahora @info obtiene el valor correcto
Por otra parte, siempre se puede utilizar paréntesis.
El binario "xor"
devuelve la OR exclusiva de las dos expresiones que le rodean. No puede cortocircuitar (por supuesto).
No existe un operador de más baja precedencia para defined-OR.
Operadores de C que faltan en Perl
Esto es lo que C tiene pero Perl no:
- unario &
-
Operador Dirección-de. (Vea, sin embargo, el operador
"\"
para tomar una referencia). - unario *
-
Operador de Desreferencia. (Los prefijos de los operadores de desreferencia de Perl están tipificados:
$
,@
,%
y&
). - (TYPE)
-
Operador de Forzado de tipo.
Comillas y operadores de comillas
Mientras solemos pensar de lo entrecomillado como si fueran valores literales, en Perl funcionan como operadores, ofreciendo diversos tipos de interpolación y capacidades de coincidencia de patrones. Perl no solo proporciona caracteres normales de entrecomillado para estos comportamientos, sino que también proporciona una manera para que usted elija su carácter de entrecomillado para cualquiera de ellos. En la siguiente tabla, un {}
representa cualquier par de delimitadores que usted elija.
Normal Genérico Significado Interpola
'' q{} Literal no
"" qq{} Literal sí
`` qx{} Comando sí*
qw{} Lista palabras no
// m{} Coincidencia sí*
qr{} Patrón sí*
s{}{} Substitución sí*
tr{}{} Transliteración no (pero vea abajo)
y{}{} Transliteración no (pero vea abajo)
<<EOF doc incrustado sí*
* excepto si el delimitador es ''.
Delimitadores no emparejados usan el mismo carácter delante y detrás, pero los otros cuatro delimitadores (paréntesis, corchetes, ángulos y llaves) pueden ser anidados, lo que significa que
q{foo{bar}baz}
es lo mismo que
'foo{bar}baz'
Nótese, sin embargo, que esto no siempre funciona para entrecomillar código Perl:
$s = q{ if($x eq "}") ... }; # MAL
es un error de sintaxis. El módulo Text::Balanced
(estándar a partir de v5.8, y anteriormente en CPAN) es capaz de hacer esto de forma correcta.
Puede haber espacios en blanco entre el operador y los caracteres delimitadores, excepto cuando #
se utiliza como carácter delimitador. q#foo#
se analiza como la cadena foo
, mientras que q #foo#
es el operador q
seguido por un comentario. Su argumento se tomará de la línea siguiente. Esto le permite escribir:
s {foo} # Reemplaza foo
{bar} # por bar.
Las siguientes secuencias de escape están disponibles en construcciones que interpolan, y en transliteraciones:
Secuencia Nota Descripción
\t tab (HT, TAB)
\n nueva línea (NL)
\r retorno (CR)
\f avance de página (FF)
\b retroceso (BS)
\a alarma (campana) (BEL)
\e escape (ESC)
\x{263A} [1,8] car. hex. (ejemplo: SMILEY)
\x1b [2,8] rango restringido car. hex (example: ESC)
\N{nombre} [3] nombre carácter o secuencia caracteres Unicode
\N{U+263D} [4,8] Carácter Unicode (ejemplo: FIRST QUARTER MOON)
\c[ [5] car. control a(ejemplo: chr(27))
\o{23072} [6,8] car. octal (ejemplo: SMILEY)
\033 [7,8] rango restringido car. octal (ejemplo: ESC)
- [1]
-
El resultado es el carácter especificado por el número hexadecimal entre las llaves. Vea "[8]" más abajo para detalles sobre el carácter.
Solo están permitidos los dígitos hexadecimales entre las llaves. Si se encuentra un carácter inválido, se emitirá una advertencia y el carácter inválido y todos los demás caracteres (válidos o no) dentro de las llaves serán descartados.
Si no hay dígitos válidos entre las llaves, el carácter generado es el carácter NULL (
\x{00}
). Sin embargo, una explícita pareja de llaves vacía (\x{}
) no provocará ninguna advertencia (actualmente). - [2]
-
El resultado es el carácter especificado por el número hexadecimal en el rango 0x00 a 0xFF. Vea "[8]" más abajo para detalles sobre el carácter.
Solo están permitidos dígitos hexadecimales si van a continuación de
\x
. Cuando\x
esté seguido por menos de dos dígitos válidos, los dígitos válidos serán rellenados con ceros. Esto significa que\x7
se interpretará como\x07
, y un único"\x"
se interpretará como un\x00
. Salvo en el final de una cadena, con menos de dos dígitos válidos, dará lugar a una advertencia. Tenga en cuenta que, si bien la advertencia dice que el carácter ilegal no se tiene en cuenta, sólo es ignorado como parte del escapado y aún así es utilizado como el carácter siguiente en la cadena. Por ejemplo:Original Resultado ¿Advertencia? "\x7" "\x07" no "\x" "\x00" no "\x7q" "\x07q" sí "\xq" "\x00q" sí
- [3]
-
El resulado es un carácter o secuencias de caracteres Unicode indicado por nombre. Vea charnames.
- [4]
-
\N{U+número hexadecimal}
equivale al carácter Unicode cuyo código de carácter Unicode sea número hexadecimal. - [5]
-
El carácter que siga a
\c
es mapeado a algún otro carácter, tal como se muestra en esta tabla:Secuencia Valor \c@ chr(0) \cA chr(1) \ca chr(1) \cB chr(2) \cb chr(2) ... \cZ chr(26) \cz chr(26) \c[ chr(27) # Mire más abajo para chr(28) \c] chr(29) \c^ chr(30) \c_ chr(31) \c? chr(127) # (en plataformas ASCII; vea más abajo para el enlace a # explicación sobre EBCDIC)
En otras palabras, es el carácter cuyo código de punto era 64 xor con su mayúscula.
\c?
es DELETE en plataformas ASCII porqueord("?") ^ 64
es 127, y\c@
es NULL porque el ord() de"@"
es 64, por lo que haciendo xor con 64 produce un 0.Además,
\c\X
es igual achr(28) . "X"
para cualquier X, pero no puede estar al final de una cadena, porque la barra diagonal inversa se interpretaría como que se estuviera escapando la comilla final.En las plataformas ASCII, los caracteres resultantes de la lista anterior son el conjunto completo de los caracteres de control ASCII. Este no es el caso en las plataformas EBCDIC; vea "DIFERENCIAS EN LOS OPERADORES" in perlebcdic para ver la discusión de las diferencias entre las plataformas ASCII y EBCDIC.
No se recomienda el uso de cualquier otro carácter después de la
"c"
, aparte de los mencionados anteriormente, y a partir de Perl v5.20, los únicos caracteres permitidos son los ASCII imprimibles, menos la llave izquierda"{"
. Lo que sucede ahora para cualquiera de los otros caracteres es que el valor se obtiene haciendo un xor con el séptimo bit, que es 64, y se levanta una advertencia si están activadas. Usar los caracteres no permitidos genera un error fatal.Para obtener caracteres de control independientes de la plataforma, se puede utilizar
\N{...}
. - [6]
-
El resultado es el carácter especificado por el número octal entre las llaves. Vea "[8]" más abajo para detalles sobre el carácter.
Si se encuentra un carácter que no es un dígito octal, se produce una advertencia, y el valor se calcula en los dígitos octales anteriores a él, descartandolo a él y a todos los caracteres siguientes hasta la llave de cierre. Es un error fatal si no hay dígitos octales.
- [7]
-
El resultado es el carácter especificado por el número octal de tres dígitos en el rango 000 a 777 (pero es mejor no superar el 077. Vea siguiente párrafo). Vea "[8]" más abajo, para detalles sobre este carácter.
Algunos contextos permiten dos o incluso un dígito, pero cualquier otro uso, sin exactamente tres dígitos, siendo el primero un cero, puede dar resultados inesperados. (Por ejemplo, en una expresión regular puede ser confundida con una retrorreferencia; vea "Secuencias de escapado octal" in perlrebackslash). A partir de Perl 5.14, puede utilizar en su lugar
\o{}
, lo que evita todos estos problemas. De lo contrario, es mejor utilizar esta construcción sólo para los ordinales\077
e inferiores, recordando que hay que rellenar a la izquierda con ceros, para tener los tres dígitos. Para ordinales más grandes, puede usar tanto\o{}
, o convertirlo a otra cosa, como por ejemplo, a hexadecimal y usar\N{U+}
(que es portable entre plataformas con conjuntos diferentes de caracteres) o usar en su lugar\x{}
. - [8]
-
Varias de las construcciones anteriores especifican un carácter a partir de un número. Este número da la posición del carácter dentro de la codificación del conjunto de caracteres (comenzando en 0). Esto se conoce, de forma similar, como su valor ordinal, posición del código, o punto de código. Perl funciona en plataformas que tienen, actualmente, una codificación nativa ASCII/Latin1 o EBCDIC, cada una de las cuales permiten la especificación de 256 caracteres. En general, si el número es 255 (0xFF, 0377) o menor, Perl lo interpreta en la codificación nativa de la plataforma. Si el número es 256 (0x100, 0400) o superior, Perl lo interpreta como un punto de código Unicode y el resultado es el correspondiente carácter Unicode. Por ejemplo, ambos
\x{50}
y\o{120}
son el número 80 en decimal, que es menos de 256, por lo que el número se interpreta en la codificación de caracteres nativa. En ASCII el carácter en la posición 80 (basado en 0) es la letra"P"
, y en EBCDIC es el símbolo del signo ampersand"&"
.\x{100}
y\o{400}
son, ambos dos, 256 en decimal, por lo que el número se interpreta como un punto de código Unicode sin importar qué codificación nativa sea. El nombre del carácter en la posición 256ª (empezando en 0) en Unicode esLATIN CAPITAL LETTER A WITH MACRON
.Hay un par de excepciones a la regla anterior.
\N{U+número hex.}
siempre se interpreta como un código de carácter Unicode, por lo que\N{U+0050}
es"P"
incluso en plataformas EBCDIC. Y siuse encoding
está en activo, el número se considera que está en esa codificación, y se traduce desde ahí a la codificación nativa de la plataforma si existe un carácter nativo correspondiente; de lo contrario, se traduce a Unicode.
NOTA: A diferencia de C y otros lenguajes, Perl no tiene una secuencia de escape \v
para el tabulado vertical (VT, que es 11 tanto en ASCII como en EBCDIC), pero puede usar \N{VT}
, \ck
, \N{U+0b}
o \x0b
. (\v
tiene significado en los patrones de las expresiones regulares en Perl, vea perlre).
Las siguientes secuencias de escape están disponibles en construcciones que interpolan, pero no en transliteraciones.
\l siguiente car. en minúscula
\u capitalizar (¡no mayúscula!) sólo el siguiente carácter
\L en minúscula todos los caracteres hasta \E o fin de cadena
\U en mayúscula todos los caracteres hasta \E o fin de cadena
\F pliega el tamaño de caja hasta \E o fin de cadena
\Q entrecomilla (deshabilita) los metacaracteres de patrón hasta \E o
final de cadena
\E fin de modificación de tamaño de caja o sección entrecomillada
(lo que se haya visto por última vez)
Vea "quotemeta" in perlfunc para la definición exacta de los caracteres que son escapados por \Q
.
\L
, \U
, \F
y \Q
pueden apilarse, en cuyo caso necesita un \E
para cada uno. Por ejemplo:
say "Este \Qtrabajo de \uescapado \Uaún no se ha\E terminado,\E ¿no?";
Este trabajo\ de\ Escapado\ AÚN\ NO\ SE\ HA\ terminado\, ¿no?
Si una forma de use locale
que incluya a LC_CTYPE
está en vigor (vea perllocale), el mapeo de tamaños de caja usado por \l
, \L
, \u
y \U
se toma de la configuración regional actual. Si se usa Unicode (por ejemplo, \N{}
o códigos de carácter de 0x100 o superiores), el mapeo de tamaño de caja usado por \l
, \L
, \u
y \U
se define por Unicode. Esto significa que el mapeo de un único carácter a veces puede producir una secuencia de varios caracteres. Bajo use locale
, \F
produce los mismos resultados que \L
para todas las configuraciones regionales excepto UTF-8, donde, en su lugar, se usa la definición Unicode.
Todos los sistemas usan el carácter virtual "\n"
para representar un terminador de línea, llamado un "nueva línea". No existe tal cosa como un invariable o físico, carácter de nueva línea. Es sólo una ilusión que el sistema operativo, controladores de dispositivo, bibliotecas de C, y Perl, conspiran para preservar. No todos los sistemas leen "\r"
como ASCII CR y "\n"
como ASCII LF. Por ejemplo, en los antiguos Mac (pre MacOS X) de antaño, estos solían estar invertidos, y en los sistemas sin un terminador de línea, la impresión de un "\n"
podría no emitir ningún dato real. En general, utilice "\n"
cuando se refiera a una "nueva línea" para su sistema, pero use el literal ASCII cuando necesite un carácter exacto. Por ejemplo, la mayoría de protocolos de red esperan y prefieren un CR+LF ("\015\012"
o "\cM\cJ"
) como terminadores de línea, y aunque a menudo aceptan sólo "\012"
, rara vez tolerarán sólo un "\015"
. Si se mete en el hábito de usar "\n"
en la gestión de redes, es posible que un día se queme.
Para las construcciones que hacen interpolación, las variables que empiezan por "$
" o "@
" son interpoladas. Variables con subrangos, como $a[3]
o $href->{clave}[0]
son también interpoladas, así como trozos de array y hash. Pero llamadas a métodos como $objeto->metodo
, no.
Interpolar un array o una parte de él, es interpolar los elementos por orden, separándolos por el valor de $"
, que es equivalente a interpolar join $", @array
. Los arrays de "puntuación" como @*
son normalmente interpolados solo si el nombre está encerrado entre llaves @{*}
, pero los arrays @_
, @+
, y @-
son interpolados, incluso sin llaves.
Para las cadenas con comillas dobles, el efecto de \Q
es aplicado después del procesado de la interpolación y el escapado.
"abc\Qfoo\tbar$s\Exyz"
es equivalente a
"abc" . quotemeta("foo\tbar$s") . "xyz"
Para el patrón de los operadores regex (qr//
, m//
y s///
), el efecto de \Q
es aplicado después de que se haya procesado la interpolación, pero antes de que sean procesados los escapados. Esto permite que el patrón coincida literalmente (a excepción de $
y @
). Por ejemplo, lo siguiente coincide:
'\s\t' =~ /\Q\s\t/
Debido a que $
o @
disparan la interpolación, tendrá que usar algo como /\Quser\E\@\Qhost/
para coincidir con ellos literalmente.
Los patrones están sujetos a un nivel adicional de interpretación como una expresión regular. Esto se hace como un segundo paso, después de que las variables sean interpoladas, así las expresiones regulares pueden incorporarse en patrones desde las variables. Si no es esto lo que quiere hacer, use \Q
para interpolar una variable literalmente.
Además de los comportamientos descritos anteriormente, Perl no expande múltiples niveles de interpolación. En particular, contrariamente a las expectativas de los programadores de shell, las comillas invertidas NO interpolan entre comillas dobles, ni las comillas simples impiden la evaluación de las variables cuando se usan dentro de comillas dobles.
Operadores regex entrecomillados
Aquí están los operadores, parecidos a los de entrecomillado, que se aplican a las actividades relacionadas con la coincidencia.
qr/CADENA/msixpodualn
-
Este operador entrecomilla (y posiblemente compila) CADENA como una expresión regular. CADENA se interpola de la misma manera que PATRÓN en
m/PATRÓN/
. Si se usa"'"
como delimitador, no se realiza ninguna interpolación. Devuelve un valor de Perl que puede utilizarse en lugar de la correspondiente expresión/CADENA/msixpodualn
. El valor devuelto es una versión normalizada del patrón original. Mágicamente se distingue de una cadena que contenga los mismos caracteres:ref(qr/x/)
devuelve "Regexp"; sin embargo, desreferenciarla no está bien definido (actualmente obtendrá la versión normaliza del patrón original, pero esto puede cambiar).Por ejemplo,
$rex = qr/mi.CADENA/is; print $rex; # imprime (?si-xm:mi.CADENA) s/$rex/foo/;
es equivalente a
s/mi.CADENA/foo/is;
El resultado puede utilizarse como un sub-patrón en una coincidencia:
$re = qr/$patron/; $cadena =~ /foo${re}bar/; # se puede interpolar en otros # patrones $cadena =~ $re; # o usado de forma aislada $cadena =~ /$re/; # o de esta manera
Debido a que Perl puede compilar el patrón en el momento de la ejecución del operador
qr()
, usarqr()
puede tener ventajas de velocidad en algunas situaciones, notablemente si el resultado deqr()
se utiliza de forma independiente:sub coincidencia { my $patrones = shift; my @compilados = map qr/$_/i, @$patrones; grep { my $exito = 0; foreach my $pat (@compilados) { $exito = 1, last if /$pat/; } $exito; } @_; }
La precompilación del patrón en una representación interna en el momento de
qr()
evita la necesidad de recompilar el patrón cada vez que se intente una coincidencia de/$pat/
. (Perl tiene otras muchas optimizaciones internas, pero ninguna se activará en el ejemplo anterior si no usamos el operadorqr()
).Opciones (especificado por los siguientes modificadores) son:
m Trata la cadena como un conjunto de múltiples líneas s Trata la cadena como una única línea (Hace que . coincida con un car. de nueva línea) i Hace coincidencia de patrones independiente del tamaño de caja x Usa expresiones regulares extendidas p Cuando exista una coincidencia preserva una copia de la cadena concordante, de tal manera que ${^PREMATCH}, ${^MATCH} y ${^POSTMATCH} quedarán definidos (ignorados a partir de v5.20) como si siempre estuvieran definidos a partir de ese versión o Compila el patrón solo una vez a ASCII-restrictivo: Use ASCII para \d, \s, \w; especificando dos "a" ofrece más restricciones a lo que un carácter no ASCII coincida con ningún carácter que no sea ASCII bajo /i. l Usa las reglas en tiempo de ejecución de la configuración regional actual. u Usa las reglas Unicode d Usa el conjunto de caracteres Unicode o nativo, como en 5.12 y anteriores n Modo de no captura. Impide que () establezca $1, $2, etc...
Si un patrón precompilado se incrusta en un patrón más grande entonces los efectos de
"msixpluadn"
se propagarán apropiadamente. El efecto del modificador/o
no se propaga; se limita a los patrones que lo utilicen de forma explícita.Los últimos cuatro modificadores enumerados anteriormente, agregados en Perl 5.14, controlan las reglas del juego de caracteres, pero
/a
es el único que querrá especificar explícitamente; los otros tres se seleccionan automáticamente por medio de diversos pragmas.Vea perlre para obtener información adicional sobre la sintaxis válida para CADENA, y para una vista detallada de la semántica de las expresiones regulares. En particular, todos los modificadores, excepto el largamente obsoleto
/o
se explican más adelante en "Modificadores" in perlre./o
se describe en la sección siguiente. m/PATRÓN/msixpodualngc
/PATRÓN/msixpodualngc
-
Busca una cadena para una coincidencia de patrones, y en un contexto escalar devuelve verdadero si tiene éxito, falso si falla. Si no se especifica una cadena con los operadores
=~
o!~
, se busca en la cadena$_
. (La cadena especificada con=~
no tiene por qué ser un valor-izquierda: puede ser el resultado de una evaluación de una expresión, pero recuerde que=~
tiene una precedencia más alta). Vea también perlre.Las opciones son como se describe anteriormente en
qr//
; además, los siguientes modificadores de coincidencia están disponibles:g Coincidencia global, es decir, busca todas las ocurrencias. c No reinicia la posición de búsqueda en una coincidencia fallida cuando /g está activa.
Si
"/"
es el delimitador entonces la inicialm
es opcional. Con lam
puede usar cualquier par de caracteres no-blancos (ASCII) como delimitadores. Esto es particularmente útil para hacer coincidencia con los nombres de ruta que contienen"/"
, para evitar el "síndrome del palillo de dientes". Si"?"
es el delimitador, entonces se aplica la regla coincide-solo-una-vez, descrita más abajo, enm?PATRÓN?
. Si"'"
(comilla simple) es el delimitador, no se realiza ninguna interpolación en el PATRÓN. Cuando se utiliza un carácter delimitador que puede ser válido en un identificador, se requiere un espacio en blanco después de lam
.PATRÓN puede contener variables, que serán interpoladas cada vez que se evalúe el patrón de búsqueda, a excepción de cuando el delimitador sea una comilla simple. (Tenga en cuenta que
$(
,$)
, y$|
no son interpoladas porque tienen la apariencia de test de final-de-cadena). Perl no recompilará el patrón a menos que cambie una variable que vaya a interpolarse. Puede forzar a Perl para saltar el test y nunca volver a recompilar, mediante la adición de un/o
(que significa "una vez") después del delimitador final. Hace algún tiempo, Perl hubiera recompilado expresiones regulares innecesariamente, y este modificador era útil para decirle que no lo hiciese, en aras de aumentar la velocidad. Pero ahora, las únicas razones para utilizar/o
son una de estas:Las variables tienen miles y miles de caracteres de longitud y sabe que no cambiarán, y necesita exprimir hasta la última gota de la velocidad de Perl, obviando estas pruebas. (Hay un castigo en el mantenimiento, al hacer esto, porque al usar
/o
constituye una promesa de que no va a cambiar las variables que hay dentro del patrón. Si las cambia, Perl ni siquiera se dará cuenta).desea que el patrón use los valores iniciales de las variables, independientemente de si van a cambiar o no. (Pero hay formas más sanas de lograr esto que usando
/o
).Si el patrón contiene código incrustado, como lo siguiente:
use re 'eval'; $codigo = 'foo(?{ $x })'; /$codigo/
entonces perl lo recompilará en cada ocasión, incluso aunque la cadena del patrón no cambie, para asegurarse que el valor de
$x
es analizado en cada ocasión. Use/o
, si quiere evitarlo.
La conclusión es que el uso de
/o
casi nunca es una buena idea. - El patrón vacío
//
-
Si el PATRÓN se evalúa como la cadena vacía, se usa en su lugar la última exitosa expresión regular coincidente. En este caso, sólo las opciones
g
yc
en el patrón vacío se toman en cuenta; las otras opciones se toman del patrón original. Si no hubo una coincidencia exitosa, actuará (silenciosamente) como un verdadero patrón vacío (que siempre coincidirá con cualquier cadena).Tenga en cuenta que es posible confundir a Perl haciéndolo creer que
//
(la expresión regular vacía) es en realidad//
(el operador definido-o). Perl es, por lo general, bastante bueno en esto, pero algunos casos patológicos podrían dar lugar a esa confusión, como en$x///
(¿esto es($x) / (//)
o$x // /
?) yprint $fh //
(¿print $fh(//
oprint($fh //
?) En todos estos ejemplos, Perl asumirá que significaba definido-o. Si lo que quiere expresar es una expresión regular vacía, sólo tiene que utilizar paréntesis o espacios para eliminar la ambigüedad, o incluso el prefijar con unam
(así que//
se convierte enm//
). - Coincidencia en contexto de lista
-
Si no se utiliza la opción
/g
,m//
en contexto de lista devuelve una lista compuesta de las subexpresiones coincidentes por los paréntesis en el patrón, es decir, ($1
,$2
,$3
...). (Tenga en cuenta que$1
y demás también son ajustados). Cuando no hay paréntesis en el patrón, en caso de éxito el valor de retorno es la lista(1)
. Con o sin paréntesis, se devuelve una lista vacía en caso de error.Ejemplos:
open(TTY, "+>/dev/tty"); || die "no puedo acceder a /dev/tty: $!"; <TTY> =~ /^s/i && foo(); # hacer foo() si así se desea if (/Version: *([0-9.]*)/) { $version = $1; } next if m#^/usr/spool/uucp#; # un grep para pobres $arg = shift; while (<>) { print if /$arg/o; # compilar solo una vez (¡ya no es necesario!) } if (($F1, $F2, $Etc) = ($foo =~ /^(\S+)\s+(\S+)\s*(.*)/))
Este último ejemplo divide
$foo
en las dos primeras palabras y el resto de la línea, y asigna los tres campos a$F1
,$F2
, y$Etc
. La condición es verdadera si cualquiera de las variables fue establecida; es decir, si el patrón coincidió.El modificador
/g
especifica concordancia global del patrón, es decir, coincidencia tantas veces como sea posible dentro de la cadena. El cómo se comporta depende del contexto. En contexto de lista, devuelve una lista de las subcadenas coincidentes con los paréntesis de captura de la expresión regular. Si no hay paréntesis, devuelve una lista de todas las cadenas coincidentes, como si hubiera paréntesis alrededor de todo el patrón.En contexto escalar, cada ejecución de
m//g
encuentra la siguiente coincidencia, devolviendo verdadero si coincide, y falso si no hay ninguna coincidencia más. La posición después de la última coincidencia puede ser leída o establecida mediante la funciónpos()
; vea "pos" in perlfunc. Una coincidencia fallida, normalmente, restablece la posición de búsqueda al principio de la cadena, pero puede evitarlo añadiendo el modificador/c
(por ejemplom//gc
). Modificando la cadena objetivo también restablece la posición de búsqueda. aserción \G
-
Puede entremezclar coincidencias
m//g
conm/\G.../g
, donde\G
es una aserción de ancho cero que coincide con la posición exacta en que la anteriorm//g
, si hubo, se detuvo. Sin el modificador/g
, la aserción\G
aún se ancla en pos() como si fuera al principio de la operación (vea "pos" in perlfunc), pero la coincidencia, por supuesto, sólo se prueba una vez. Usando\G
sin/g
en una cadena objetivo que no haya tenido anteriormente aplicada una coincidencia/g
es lo mismo que usar la aserción\A
para que coincida con el principio de la cadena. Tenga en cuenta también que, actualmente,\G
está sólo adecuadamente soportada cuando se fija al comienzo del patrón.Ejemplos:
# contexto lista ($uno,$cinco,$quince) = (`uptime` =~ /(\d+\.\d+)/g); # contexto escalar local $/ = ""; while ($parrafo = <>) { while ($parrafo =~ /\p{Ll}['")]*[.!?]+['")]*\s/g) { $sentencias++; } } say $sentencias;
Aquí hay otra forma de buscar sentencias en un párrafo:
my $sentencia_rx = qr{ (?: (?<= ^ ) | (?<= \s ) ) # después de inicio-de-cadena o # espacio en blanco \p{Lu} # letra mayúscula .*? # un montón de nada (?<= \S ) # que termina en un no # espacio en blanco (?<! \b [DMS]r ) # pero no es una abreviatura conocida (?<! \b Mrs ) (?<! \b Sra ) (?<! \b St ) [.?!] # seguido por una sentencia # terminada (?= $ | \s ) # delante de un final-de-cadena # o espacio en blanco }sx; local $/ = ""; while (my $parrafo = <>) { say "NUEVO PÁRRAFO"; my $cuenta = 0; while ($parrafo =~ /($sentencia_rx)/g) { printf "\tnueva sentencia %d: <%s>\n", ++$cuenta, $1; } }
Aquí está cómo se usa
m//gc
con\G
:$_ = "ppooqppqq"; while ($i++ < 2) { print "1: '"; print $1 while /(o)/gc; print "', pos=", pos, "\n"; print "2: '"; print $1 if /\G(q)/gc; print "', pos=", pos, "\n"; print "3: '"; print $1 while /(p)/gc; print "', pos=", pos, "\n"; } print "Final: '$1', pos=",pos,"\n" if /\G(.)/;
El último ejemplo debería imprimir:
1: 'oo', pos=4 2: 'q', pos=5 3: 'pp', pos=7 1: '', pos=7 2: 'q', pos=8 3: '', pos=8 Final: 'q', pos=8
Observe que el último emparejamiento es
q
en vez dep
, que una coincidencia sin el anclaje\G
habría hecho. También tenga en cuenta que la última coincidencia no actualizópos
.pos
sólo es actualizado en una coincidencia/g
. En cambio, si la última coincidencia fuep
, hay buenas posibilidades de que está ejecutando una versión anterior de Perl (pre-5.6.0).Un modismo útil para escáneres tipo
lex
es/\G.../gc
. Puede combinar varias expresiones regulares como ésta para procesar una cadena parte por parte, haciendo diferentes acciones dependiendo de la expresión regular coincidente. Cada regex intenta coincidir donde la anterior lo dejó.$_ = <<'EOL'; $url = URI::URL->new( "http://example.com/" ); die if $url eq "xXx"; EOL BUCLE: { print(" dígitos"), redo LOOP if /\G\d+\b[,.;]?\s*/gc; print(" minúscula"), redo LOOP if /\G\p{Ll}+\b[,.;]?\s*/gc; print(" MAYÚSCULA"), redo LOOP if /\G\p{Lu}+\b[,.;]?\s*/gc; print(" Capitalizada"), redo LOOP if /\G\p{Lu}\p{Ll}+\b[,.;]?\s*/gc; print(" MeZcLaDoS"), redo LOOP if /\G\pL+\b[,.;]?\s*/gc; print(" alfanumérico"), redo LOOP if /\G[\p{Alpha}\pN]+\b[,.;]?\s*/gc; print(" línea-ruido"), redo LOOP if /\G\W+/gc; print ". ¡Eso es todo!\n"; }
Aquí está la salida (dividido en varias líneas):
línea-ruido minúsculas línea-ruido MAYÚSCULAS línea-ruido MAYÚSCULAS línea-ruido minúsculas línea-ruido minúsculas línea-ruido minúsculas minúsculas línea-ruido minúsculas minúsculas línea-ruido minúsculas minúsculas línea-ruido MeZcLaDoS línea-ruido. ¡Eso es todo!
m?PATRÓN?msixpodualngc
?PATRÓN?msixpodualngc
-
Esto es igual que la búsqueda
m/PATRÓN/
, salvo que coincide una sola vez entre llamadas al operadorreset()
. Esta es una optimización útil cuando se desea ver sólo la primera aparición de algo en cada archivo de un conjunto de archivos, por ejemplo. Sólo se reinicializan los patrones localesm??
del paquete actual.while (<>) { if (m?^$?) { # línea en blanco entre cabecera y cuerpo } } continue { reset if eof; # limpiar el estado de m?? para el siguiente archivo }
En este otro ejemplo se cambia la primera ocurrencia de la codificación "latin1" que se encuentra a "utf8", en un archivo pod:
s//utf8/ if m? ^ =encoding \h+ \K latin1 ?x;
El comportamiento de la coincidencia de una sola vez, se controla por el delimitador que comienza por
?
; con cualquier otro delimitador, se trata del habitual operadorm//
.En el pasado, la
m
precedente enm?PATRÓN?
era opcional, pero omitirlo produciría una advertencia de obsolescencia. A partir de v5.22.0, omitirlo produce un error de sintaxis. Si encuentra esta construcción en código antiguo, solo tiene que añadirm
. s/PATRÓN/REEMPLAZO/msixpodualngcer
-
Busca un patrón en una cadena, y si se encuentra, sustituye este patrón con el texto de reemplazo y devuelve el número de sustituciones. De lo contrario, devuelve falso (en concreto, la cadena vacía).
Si la opción
/r
(no destructiva) es utilizada, entonces llevará a cabo la sustitución en una copia de la cadena y en lugar de devolver el número de sustituciones, devuelve la copia, haya o no ocurrido una sustitución. La cadena original no se cambia nunca cuando/r
se utiliza. La copia siempre será una cadena normal, incluso si la entrada es un objeto o una variable enlazada.Si no se especifica una cadena a través de los operadores
=~
o!~
, se utiliza la variable$_
para la búsqueda y la modificación. A menos que se use la opción/r
, la cadena especificada debe ser una variable escalar, un elemento de un array, un elemento hash, o una asignación a una de estas; es decir, algún tipo de valor-izquierda escalar.Si el delimitador elegido es una comilla simple, no se realiza ninguna interpolación, ni en el PATRÓN ni en el REEMPLAZO. De lo contrario, si el PATRÓN contiene un
$
que parece más una variable que una marca de fin de cadena, la variable se interpolará en el patrón, en tiempo de ejecución. Si desea que el patrón se compile solo la primera vez que la variable se interpole, utilice la opción/o
. Si el patrón se evalúa a la cadena vacía, se utiliza en su lugar la última expresión regular ejecutada con éxito. Vea perlre para una explicación más detallada sobre esto.Las opciones son como las de
m//
con la adición de las específicas opciones de reemplazo siguientes:e Evalúa el lado derecho como una expresión. ee Evalúa el lado derecho como una cadena que es pasada por eval() para obtener el resultado. r Devuelve la sustitución y deja la cadena original intacta.
Cualquier delimitador distinto del espacio en blanco puede sustituir a las barras diagonales. Añadir un espacio después de la
s
cuando se utilice un carácter permitido en identificadores. Si se utilizan comillas simples, no se realiza ninguna interpretación en la cadena de reemplazo (sin embargo, el modificador/e
reemplaza a ésta). Note que Perl trata las comillas simples invertidas como delimitadores normales; el texto de reemplazo no se evalúa como un comando. Si el PATRÓN está delimitado por paréntesis, corchetes o llaves, el REEMPLAZO tiene su propio par de delimitadores, que puede o no estar encerrado entre los mismos delimitadores; por ejemplo,s(foo)(bar)
os<foo>/bar/
. Un/e
hará que la parte de reemplazo sea tratada como una verdadera expresión Perl y evaluada ahí y en ese mismo momento. Será, sin embargo, comprobada la sintaxis en tiempo de compilación. Un segundo modificadore
hará que la parte de reemplazo seaeval
uada antes de la ejecución como una expresión Perl.Ejemplos:
s/\bverde\b/malva/g; # no cambia verdeazul $ruta =~ s|/usr/bin|/usr/local/bin|; s/Login: $foo/Login: $bar/; # patrón en tiempo de ejecución ($foo = $bar) =~ s/este/aquel/; # primero copiar, luego # cambiar ($foo = "$bar") =~ s/este/aquel/; # convierte a cadena, # copia y luego cambia $foo = $bar =~ s/este/aquel/r; # Lo mismo que antes usando /r $foo = $bar =~ s/este/aquel/r =~ s/aquel/el otro/r; # Sustituciones encadenadas # usando /r @foo = map { s/este/aquel/r } @bar # /r es muy útil con # map $contador = ($parrafo =~ s/Señor\b/Sr./g); # obtener el número de cambios $_ = 'abc123xyz'; s/\d+/$&*2/e; # queda como 'abc246xyz' s/\d+/sprintf("%5d",$&)/e; # queda como 'abc 246xyz' s/\w/$& x 2/eg; # queda como 'aabbcc 224466xxyyzz' s/%(.)/$porciento{$1}/g; # cambia los escapados con el %; sin /e s/%(.)/$porciento{$1} || $&/ge; # ahora es una expr., así que /e s/^=(\w+)/pod($1)/ge; # usa una función de llamada $_ = 'abc123xyz'; $x = s/abc/def/r; # $x es 'def123xyz' y # $_ queda como 'abc123xyz' # expandir variables en $_, pero solo dinámicamente, usando # desreferencia simbólica s/\$(\w+)/${$1}/g; # Suma uno al valor de todos los números en la cadena s/(\d+)/1 + $1/eg; # Solo palabras con capitulares en los últimos 30 caracteres substr($str, -30) =~ s/\b(\p{Alpha}+)\b/\u\L$1/g; # Esto expandirá cualquier variable escalar incrustada # (incluyendo léxicas) en $_ : Primero $1 se interpola # al nombre de la variable, y entonces, se evalúa s/(\$\w+)/$1/eeg; # Eliminar (la mayoría de) comentarios de C. $programa =~ s { /\* # Busca el delimitador de apertura. .*? # Busca el mínimo número de caracteres. \*/ # Busca el delimitador de cierre. } []gsx; s/^\s*(.*?)\s*$/$1/; # recorta el espacio en blanco en $_, # de forma onerosa for ($variable) { # recorta el espacio en blanco en $variable, # de forma más simple s/^\s+//; s/\s+$//; } s/([^ ]*) *([^ ]*)/$2 $1/; # invierte los dos primeros campos
Note el uso de
$
en lugar de\
en el último ejemplo. A diferencia de sed, utilizamos el formato \<dígito> sólo en el lado izquierdo. En cualquier otro lugar, es $<dígito>.De vez en cuando, no puede utilizar un simple
/g
para obtener todos los cambios posibles. Aquí hay dos casos comunes:# pone comas en los lugares adecuados en un entero 1 while s/(\d)(\d\d\d)(?!\d)/$1,$2/g; # expandir tabuladores a un espaciado de 8 columnas 1 while s/\t+/' ' x (length($&)*8 - length($`)%8)/e;
Operadores de entrecomillado
q/CADENA/
'CADENA'
-
Una cadena de caracteres literal, con un simple entrecomillado. Una barra diagonal inversa representa una barra diagonal inversa a menos que esté seguida por el delimitador u otra barra diagonal inversa, en cuyo caso el delimitador o la barra diagonal inversa son interpolados.
$foo = q!Yo dije, "Tú dijiste, 'Ella dijo.'"!; $bar = q('Así es.'); $baz = '\n'; # una cadena de dos caracteres
qq/CADENA/
- "CADENA"
-
Un doble entrecomillado, la cadena se interpola.
$_ .= qq (*** La línea anterior contiene la palabra juguetona "$1".\n) if /\b(tcl|java|python)\b/i; # :-) $baz = "\n"; # una cadena de un carácter
qx/CADENA/
`CADENA`
-
Una cadena que es (posiblemente) interpolada y entonces ejecutada como un comando del sistema con /bin/sh o su equivalente. Los comodines del intérprete, tuberías y redirecciones serán respetados. Todo lo que salga por la salida estándar del comando se devuelve; la salida estándar de error no se verá afectada. En contexto escalar, se devuelve como una sola cadena de caracteres (con, posiblemente, múltiples líneas dentro), o
undef
si el comando ha fallado. En contexto de lista, devuelve una lista de líneas (según haya definido líneas con$/
o$INPUT_RECORD_SEPARATOR
), o una lista vacía si el comando ha fallado.Como las comillas invertidas no afectan a la salida de error estándar, use la sintaxis del shell del descriptor de archivos (asumiendo que el shell soporte esto) si es que quiere tenerlo en cuenta. Para capturar el STDOUT y STDERR del comando, juntos:
$salida = `comando 2>&1`;
Para capturar el STDOUT de un comando pero descartar su STDERR:
$salida = `comando 2>/dev/null`;
Capturar el STDERR de un comando pero descartar su STDOUT (aquí, el orden es importante):
$salida = `comando 2>&1 1>/dev/null`;
Intercambiar el STDOUT y STDERR de un comando para capturar el STDERR pero dejando que su STDOUT salga por el anterior STDERR:
$salida = `comando 3>&1 1>&2 2>&3 3>&-`;
Para leer tanto el STDOUT como el STDERR de un comando, pero de forma separada, es más fácil hacerlos redireccionar de forma separada a archivos, y luego leer esos archivos cuando el programa termine:
system("programa argumentos 1>programa.stdout 2>programa.stderr");
El identificador de archivo STDIN utilizado por el comando se hereda del STDIN de Perl. Por ejemplo:
open(SPLAT, "stuff") || die "no puedo abrir stuff: $!"; open(STDIN, "<&SPLAT") || die "no puedo duplicar SPLAT: $!"; print STDOUT `sort`;
imprimirá los contenidos ordenados del archivo nombrado como "stuff".
Usando comillas simples como delimitadores impide la interpolación del doble entrecomillado de Perl, pasándolo, en su lugar, al shell:
$perl_info = qx(ps $$); # es el $$ de Perl $shell_info = qx'ps $$'; # es el $$ del nuevo shell
El cómo se evalúa esta cadena está sujeto enteramente al intérprete de comandos de su sistema. En la mayoría de plataformas, tendrá que proteger los metacaracteres de shell, si quiere que sean tratados de forma literal. Esto en la práctica es difícil de hacer, como que no está claro cómo escapar qué caracteres. Vea perlsec para un ejemplo seguro y limpio de un
fork()
yexec()
manual para emular comillas invertidas de forma segura.En algunas plataformas (especialmente las de tipo DOS), el shell quizás no pueda ser capaz de tratar con los comandos de múltiples líneas, así que poner saltos de línea quizás no le permita obtener lo que quiere. Quizás sea capaz de evaluar múltiples comandos en una sola línea, separándoles con el carácter separador de comandos, si el shell lo soporta (por ejemplo,
;
en muchos shell Unix, y&
en el shellcmd
de Windows NT).Perl intentará vaciar todos los archivos abiertos para salida antes de iniciar un proceso hijo, pero esto puede no estar soportado en todas las plataformas (vea perlport). Para estar seguro, es posible que necesite establecer
$|
($AUTOFLUSH
enEnglish
) o llamar al métodoautoflush()
deIO::Handle
en cualquier identificador de archivo abierto.Tenga en cuenta que algunos shell de comandos pueden imponer restricciones a la longitud de la línea de comandos. Debe asegurarse de que sus cadenas de texto no superan ese límite después de cualquier interpolación necesaria. Vea las notas específicas de la plataforma para obtener más detalles acerca de su entorno particular.
Usando este operador puede dar lugar a programas que son difíciles de portar, porque el shell de comandos varía entre sistemas, y de hecho no pueden estar presentes en todos. Como ejemplo, el comando
type
en el shell POSIX es muy diferente del comandotype
en DOS. Eso no significa que deba evitar las comillas invertidas cuando sea la forma correcta de hacer algo. Perl fue creado para ser un lenguaje pegamento, y una de las cosas que aglutina, son los comandos. Sólo entienda en lo que se está metiendo.Como
system
, las comillas invertidas ponen el código de salida del proceso hijo en$?
. Si desea inspeccionar manualmente el error, puede comprobar todas las posibles causas del error mediante la inspección de$?
, de esta manera:if ($? == -1) { print "error al ejecutar: $!\n"; } elsif ($? & 127) { printf "hijo muerto con señal %d, %s coredump\n", ($? & 127), ($? & 128) ? 'con' : 'sin'; } else { printf "hijo terminó con valor %d\n", $? >> 8; }
Vea "Operadores E/S" para más discusiones sobre esto.
qw/CADENA/
-
Evalúa a una lista de palabras extraídas de CADENA, utilizando los espacios en blanco intermedios como delimitadores de palabras. Puede ser entendida como equivalente a:
split(" ", q/CADENA/);
siendo diferente en que genera una lista real en tiempo de compilación, y en contexto escalar devuelve el último elemento de la lista. Así que esta expresión:
qw(foo bar baz)
es semánticamente equivalente a la lista:
"foo", "bar", "baz"
Algunos ejemplos que suelen encontrarse frecuentemente:
use POSIX qw( setlocale localeconv ) @EXPORT = qw( foo bar baz );
Un error común es tratar de separar las palabras con comas o poner comentarios en una cadena
qw
multilínea. Por esta razón, el pragmause warnings
y la opción -w (es decir, la variable$^W
) produce advertencias si la CADENA contiene la","
o el carácter"#"
. tr/LISTA_BÚSQUEDA/LISTA_REEMPLAZO/cdsr
y/LISTA_BÚSQUEDA/LISTA_REEMPLAZO/cdsr
-
Translitera todas las apariciones de los caracteres que se encuentran en la lista de búsqueda con el carácter correspondiente en la lista de reemplazo. Devuelve el número de caracteres sustituidos o eliminados. Si no se especifica una cadena a través de los operadores
=~
o!~
, se translitera la cadena$_
.Si la opción
/r
(no-destructiva) está presente, se crea una nueva copia de la cadena y sus caracteres transliterados, y esta copia es devuelta sin importar si fue modificada o no: la cadena original siempre permanece sin cambios. La nueva copia siempre será una cadena normal, incluso si la entrada es un objeto o una variable enlazada.A menos que se use la opción
/r
, la cadena especificada con=~
debe ser una variable escalar, un elemento de un array, un elemento hash, o una asignación a una de estas, es decir, un valor-izquierda.Un intervalo de caracteres se puede especificar con un guión, por lo que
tr/A-J/0-9/
es la sustitución detr/ACEGIBDFHJ/0246813579/
. Para los devotos de sed,y
se ofrece como un sinónimo detr
. Si la LISTA_BÚSQUEDA está delimitada por sus propios delimitadores, la LISTA_REEMPLAZO tiene su propio par de delimitadores, que pueden o no ser los mismos delimitadores que los primeros. Por ejemplo,tr[aeiouy][yuoiea]
otr(+\-*/)/ABCD/
.Los caracteres pueden ser literales o cualquier secuencia de escape aceptada en las cadenas de caracteres doblemente entrecomilladas. Pero no hay interpolación, así que
"$"
y"@"
son tratados literalmente. Un guión al comienzo o final, o precedido por una barra diagonal inversa, se considera un literal. Los detalles sobre las secuencias de escape están en la tabla cerca del comienzo de esta sección.Tenga en cuenta que
tr
no usa expresiones regulares de clases de caracteres, tales como\d
o\pL
. El operadortr
no es equivalente a la utilidadtr(1)
. Si desea mapear cadenas entre minúsculas/mayúsculas, vea "lc" in perlfunc y "uc" in perlfunc; y, en general, considere usar el operadors
si necesita usar expresiones regulares. Las secuencias de escapado en la interpolación de cadenas (\U
,\u
,\L
, y\l
) en el lado derecho de un operador de sustitución realizará un correcto mapeado entre mayúsculas y minúsculas, perotr[a-z][A-Z]
, no (excepto en algunos viejos sistemas de 7 bits).La mayor parte de los rangos no son portables entre los conjuntos de caracteres, pero algunos de ellos le indican a Perl a hacer un manejo especial, para hacerlos portable. Existen dos clases de rangos portables. El primero es cualquier subconjunto de los rangos
A-Z
,a-z
y0-9
, cuando se expresa como caracteres literales.tr/h-k/H-K/
capitaliza las letras
"h"
,"i"
,"j"
y"k"
y nada más, sin importar de qué plataforma sea el conjunto de caracteres. En contraste, todos estastr/\x68-\x6B/\x48-\x4B/ tr/h-\x6B/H-\x4B/ tr/\x68-k/\x48-K/
hacen la misma capitalización como en el anterior ejemplo cuando se ejecuta en plataformas ASCII, pero algo completamente diferente en las EBCDIC.
La segunda clase de rangos portables se invocan cuando uno o ambos de los puntos finales del rango se expresan como
\N{...}
$cadena =~ tr/\N{U+20}-\N{U+7E}//d;
elimina de
$cadena
todos los caracteres de la plataforma que son equivalentes a cualquiera de los caracteres Unicode U+0020, U+0021, ... U+007D, U+007E. Este es un rango portable, y tiene el mismo efecto en todas las plataformas donde se ejecute. Resulta que en este ejemplo, existen caracteres ASCII imprimibles. Después de ejecutarlo,$cadena
solo tiene caracteres de control y caracteres que no tienen equivalentes en ASCII.Pero, incluso para rangos portables, no es, generalmente, obvio, lo que se incluye sin mirarlo con detalle. Un buen principio es el de usar solo rangos que comiencen y terminen con caracteres alfabéticos ASCII del mismo tipo (
b-e
,b-E
), o dígitos (1-4
). Todo lo demás no queda claro (ni portable a menos que se use\N{...}
). En caso de duda, explicite los conjuntos de caracteres completamente.Opciones:
c Complementa la LISTA_BÚSQUEDA. d Elimina los caracteres que se encuentren pero que no hayan sido reemplazados. s Elimina caracteres duplicados en los reemplazados. r Devuelve la cadena modificada dejando la cadena original intacta.
Si se especifica el modificador
/c
, el conjunto de caracteres LISTA_BÚSQUEDA es complementado. Si se especifica el modificador/d
, cualquier carácter especificado por LISTA_BÚSQUEDA que no se encuentre en la LISTA_REEMPLAZO, es eliminado. (Tenga en cuenta que esto es un poco más flexible que el comportamiento de algunos programas tr, que eliminan todo lo que encuentran en la LISTA_BÚSQUEDA, y punto). Si se especifica el modificador/s
, las secuencias de caracteres que se transliteren al mismo carácter son reducidas hasta una única instancia del carácter.Si se usa el modificador
/d
, la LISTA_REEMPLAZO siempre se interpreta exactamente como esté especificada. De lo contrario, si la LISTA_REEMPLAZO es más corta que la LISTA_BÚSQUEDA, el carácter final se replica hasta que sea lo suficientemente larga. Si la LISTA_REEMPLAZO está vacía, la LISTA_BÚSQUEDA se replica. Esto último es útil para el recuento de caracteres de una clase o para reducir las secuencias de caracteres de una clase.Ejemplos:
$ARGV[1] =~ tr/A-Z/a-z/; # transforma a minúsculas ASCII $cnt = tr/*/*/; # cuenta los asteriscos en $_ $cnt = $sky =~ tr/*/*/; # cuenta los asteriscos en $sky $cnt = tr/0-9//; # cuenta los dígitos en $_ tr/a-zA-Z//s; # coonnttaable -> contable ($HOST = $host) =~ tr/a-z/A-Z/; $HOST = $host =~ tr/a-z/A-Z/r; # lo mismo $HOST = $host =~ tr/a-z/A-Z/r # encadenado con s///r =~ s/:/ -p/r; tr/a-zA-Z/ /cs; # cambia los caracteres no alfabéticos por un solo espacio @limpiado = map tr/a-zA-Z/ /csr, @original; # /r con map tr [\200-\377] [\000-\177]; # borra onerosamente el octavo bit
Si se dan múltiples transliteraciones para un carácter, sólo se utiliza el primero:
tr/AAA/XYZ/
transliterará cualquier A a X.
Debido a que la tabla de transliteración se construye en tiempo de compilación, ni la LISTA_BÚSQUEDA ni la LISTA_REEMPLAZO están sujetas a la interpolación del doble entrecomillado. Esto significa que si quiere usar variables, debe usar
eval()
:eval "tr/$viejalista/$nuevalista/"; die $@ if $@; eval "tr/$viejalista/$nuevalista/, 1" or die $@;
<<EOF
-
Un formato de entrecomillado orientado a líneas basado en la sintaxis shell "here-document" (documento incrustado). Siguiendo a
<<
se especifica una cadena que termine el material entrecomillado, y todas las líneas siguientes a la actual hacia abajo hasta la cadena de terminación, son el valor del elemento.La cadena de terminación puede ser un identificador (una palabra), o algún texto entrecomillado. Un identificador sin comillas funciona igual que las comillas dobles. No es necesario un espacio entre el
<<
y el identificador, a menos que el identificador esté explícitamente entrecomillado. (Si pone un espacio será tratado como un identificador nulo, que es válido, y coincide con la primera línea en blanco). La cadena de terminación debe aparecer a sí mismo (sin comillas y sin espacios en blanco que la rodeen) en la línea de terminación.Si la cadena de terminación está entrecomillada, el tipo de comillas usadas determinan el tratamiento del texto.
- Dobles comillas
-
Las dobles comillas indican que el texto será interpolado usando exactamente las mismas reglas que las cadenas con dobles comillas.
print <<EOF; El precio es $Precio. EOF print << "EOF"; # lo mismo que el anterior El precio es $Precio. EOF
- Comillas simples
-
Las comillas simples indican que el texto se va a tratar literalmente, sin interpolación de su contenido. Esto es similar a las cadenas con comillas simples, excepto que las barras diagonales inversas no tienen ningún significado especial, siendo entonces que
\\
es tratado como dos barras diagonales inversas y no una como lo harían en cualquier otra construcción entrecomillada.Al igual que en el shell, una palabra suelta entre barras diagonales inversas siguiendo a
<<
significa lo mismo que una cadena entrecomillada simple:$cost = <<'VISTA'; # hasta la ... Van a ser $10, por favor, señora. VISTA $cost = <<\VISTA; # ¡Lo mismo! Van a ser $10, por favor, señora. VISTA
Esta es la única forma de entrecomillar en Perl donde no es necesario preocuparse por el escapado del contenido, algo que los generadores de código pueden y hacen buen uso de él.
- Comillas invertidas
-
El contenido del documento incrustado es tratado como si la cadena estuviera incrustada entre comillas invertidas. Así, el contenido es interpolado como si estuviera entrecomillado doble y luego ejecutado a través del shell, devolviendo los resultados de la ejecución.
print << `EOC`; # ejecuta comando y obtén resultados echo Hola, qué tal EOC
Es posible apilar múltiples documentos incrustados en una fila:
print <<"foo", <<"bar"; # puede apilarles He dicho foo. foo He dicho bar. bar myfunc(<< "ESTE", 23, <<'ESE'); Aquí hay una línea o dos. ESTE y aquí otra. ESE
Pero no olvide que tiene que poner un punto y coma al final para terminar la instrucción, ya que Perl no sabe que no vamos a tratar de hacer esto:
print <<ABC 179231 ABC + 20;
Si desea quitar el carácter de fin de línea de los documentos incrustados, utilice
chomp()
.chomp($cadena = <<'END'); Esto es una cadena. END
Si quiere que su documento incrustado esté sangrado con el resto del código, tendrá que quitar los espacios en blanco sobrantes de cada línea manualmente:
($quote = <<'FINIS') =~ s/^\s+//gm; El camino sigue y sigue, detrás de la puerta donde comenzó. FINIS
Si utiliza un documento incrustado en una construcción delimitada, como en
s///eg
, el material entrecomillado debe seguir a la línea que sigue al delimitador<<FOO
, significando que puede estar dentro de la construcción delimitada.s/este/<<E . 'ese' el otro E . 'más '/eg;
Esto funciona así en Perl 5.18. Históricamente, era inconsistente, y tendría que escribir
s/este/<<E . 'ese' . 'más '/eg; el otro E
fuera de las evaluaciones de cadenas.
Además, no están relacionadas las reglas de entrecomillado para el identificador del fin-de-cadena con las reglas de entrecomillado de Perl.
q()
,qq()
, y similares no están soportadas, en lugar de''
y""
, y la única interpolación es para escapar el carácter de entrecomillado:print << "abc\"def"; comprobando... abc"def
Por último, las cadenas entrecomilladas no pueden abarcar múltiples líneas. La regla general es que el identificador debe ser una cadena literal. Siga con eso, y estará seguro.
Detalles sangrientos del análisis de construcciones entrecomilladas
Cuando se le presenta algo que podría tener varias interpretaciones diferentes, Perl utiliza el DWIM ("Do What I Mean", es decir, "hacer lo que quiero decir") para escoger la interpretación más probable. Esta estrategia es tan exitosa que los programadores de Perl a menudo no sospechan de la ambivalencia de lo que escriben. Pero de vez en cuando, las nociones de Perl difieren sustancialmente de lo que el autor, honestamente, quería decir.
Esta sección pretende aclarar la manera en que Perl gestiona las construcciones entrecomilladas. Aunque la razón más común para aprender esto es desentrañar laberínticas expresiones regulares, ya que los pasos iniciales del análisis son los mismos para todos los operadores de entrecomillado, todos ellos son explicados en conjunto.
La más importante regla de análisis de Perl es la primera que se explica a continuación: cuando se procesa una construcción entrecomillada, Perl primero busca el final de esa construcción; a continuación, interpreta su contenido. Si usted entiende esta regla, puede omitir la primera lectura del resto de esta sección. Las demás normas es probable que contradigan las expectativas del usuario con mucha menos frecuencia que ésta primera.
Algunos pases discutidos a continuación se realizan de forma simultanea, pero como sus resultados son los mismos, los consideramos por separado. Para diferentes construcciones de entrecomillado, Perl realiza diferentes números de pases, de uno a cuatro, pero estos pases se realizan siempre en el mismo orden.
- Encontrando el final
-
El primer paso es encontrar el final de la construcción entrecomillada. Esto resulta en guardar en una posición segura una copia del texto (entre el delimitar inicial y final), normalizado tanto como sea necesario para evitar necesitar saber cuáles eran los delimitadores originales.
Si la construcción es un documento incrustado, el delimitador final es una línea que tiene como contenido una cadena de terminación. Por lo tanto
<<EOF
es terminado por unEOF
inmediatamente seguido por un"\n"
y empezando en la primera columna de la línea de terminación. Durante la búsqueda de la línea de terminación de un documento incrustado, nada se omite. En otras palabras, las líneas que siguen a la sintaxis del documento incrustado son comparados con la línea de terminación de cadena, una a una.Se utilizan caracteres simples como delimitadores de inicio y finalización para las construcciones, salvo los documentos incrustados. Si el delimitador inicial es un carácter de puntuación (uno como
(
,[
,{
, o<
), el delimitador final es el correspondiente carácter de puntuación, de cierre (uno como)
,]
,}
, o>
). Si el delimitador de partida es un carácter no emparejado, como/
o un carácter de puntuación de cierre, el delimitador de cierre es el mismo que el delimitador de inicio. Por lo tanto, una/
termina una construcciónqq//
, mientras que un]
termina tanto las construccionesqq[]
comoqq]]
.Durante la búsqueda de caracteres delimitadores individuales, los delimitadores escapados y los
\\
son omitidos. Por ejemplo, mientras se busca por el/
final, las combinaciones de\\
y\/
son omitidas. Si los delimitadores están emparejados, las parejas anidadas también se omiten. Por ejemplo, mientras se busca un]
de cierre emparejado con el de apertura[
, se omiten todas las combinaciones de\\
,\]
y\[
, y los caracteres anidados de[
y]
se pasan también por alto. Sin embargo, cuando se usan las barras diagonales inversas como delimitadores (comoqq\\
ytr\\\
), no se omite nada. Durante la búsqueda del final, las barras diagonales inversas que escapan delimitadores u otras barras, son eliminadas (hablando más exactamente, no se copian al lugar seguro).Para construcciones con delimitadores en tres partes (
s///
,y///
, ytr///
), la búsqueda se repite una vez más. Si el primer delimitador no es un carácter de puntuación de apertura, los tres delimitadores deben ser el mismo, comos!!!
ytr)))
, en cuyo caso el segundo delimitador termina la parte izquierda y, a la vez, comienza la parte derecha. Si la parte izquierda está delimitada por signos de puntuación emparejados (es decir,()
,[]
,{}
, o<>
), la parte derecha necesita otro par de delimitadores, como ens(){}
ytr[]//
. En estos casos, los espacios en blanco y los comentarios están permitidos entre ambas partes, a pesar de que el comentario debe estar precedido, por lo menos, de un espacio en blanco; de lo contrario, un carácter esperado como inicio del comentario puede ser considerado como el delimitador de inicio de la parte derecha.Durante esta búsqueda no se presta atención a la semántica de la construcción. Por lo tanto:
"$hash{"$foo/$bar"}"
o:
m/ bar # ¡NO es un comentario, esta barra diagonal / termina m//! /x
no forman expresiones legales de entrecomillado. La parte entrecomillada termina en la primera
"
y/
, y el resto pasa a ser un error de sintaxis. Debido a que a la barra diagonal que terminabam//
le seguía unSPACE
, el ejemplo anterior no esm//x
, sino más bienm//
, sin el modificador/x
. Así que el#
incrustado se interpreta como un#
literal.Tampoco se presta atención a
\c\
(sintaxis multicarácter de control) durante esta búsqueda. Así, el segundo\
enqq/\c\/
es interpretado como una parte de\/
, y el siguiente/
no es reconocido como un delimitador. En su lugar, utilice\034
o\x1c
al final de la construcción entrecomillada. - Interpolación
-
El siguiente paso es la interpolación del texto obtenido, que ahora es independiente del delimitador. Hay múltiples casos.
<<'EOF'
-
No se realiza ninguna interpolación. Tenga en cuenta que la combinación
\\
se mantiene intacta, ya que no están disponibles delimitadores escapados para los documentos incrustados. m''
y el patrón des'''
-
No se realiza interpolación en esta etapa. Cualquier secuencia de barras diagonales inversas, incluyendo
\\
, se tratan en la fase "analizar expresiones regulares". ''
,q//
,tr'''
,y'''
y el reemplazo des'''
-
La única interpolación es la eliminación de
\
a partir de pares de\\
. Por lo tanto,"-"
entr'''
ey'''
se trata, literalmente, como un guión, y por lo tanto no está disponible en un rango de caracteres.\1
en el reemplazo des'''
no funciona como$1
. tr///
,y///
-
No se produce interpolación de variables. Combinaciones de modificación de caracteres para cambios de tamaño de caja y entrecomillado, como
\Q
,\U
, y\E
, no son reconocidos. Las otras secuencias de escape, como\200
y\t
y caracteres escapados con barras diagonales inversas, como\\
y\-
, son convertidas a literales apropiados. El carácter"-"
se trata de forma especial y por lo tanto\-
se trata como un"-"
literal. ""
,``
,qq//
,qx//
,<file*glob>
,<<"EOF"
-
\Q
,\U
,\u
,\L
,\l
,\F
(posiblemente emparejadas con\E
) se convierten a las correspondientes construcciones Perl. Así,"$foo\Qbaz$bar"
se convierte a$foo . (quotemeta("baz" . $bar))
, internamente. Las otras secuencias de escape, como\200
y\t
y caracteres escapados con barras diagonales inversas, como\\
y\-
, se reemplazan con expansiones apropiadas.Hay que hacer hincapié en que lo que caiga dentro de
\Q
y\E
se interpola de forma normal. Algo como"\Q\\E"
no tiene dentro a\E
. En cambio, tiene a\Q
,\\
, yE
, por lo que el resultado es el mismo que para"\\\\E"
. Como regla general, las barras diagonales inversas entre\Q
y\E
pueden dar lugar a resultados no intuitivos. Así,"\Q\t\E"
se convierte aquotemeta("\t")
, que es lo mismo que"\\\t"
(porque TAB no es alfanumérico). Tenga en cuenta también que:$str = '\t'; return "\Q$str";
puede conjeturar que puede estar muy cerca de la intención de quien escribió
"\Q\t\E"
.Escalares interpolados y arrays se convierten, internamente, a las operaciones de concatenación
join
y"."
. Así,"$foo XXX '@arr'"
se convierte en:$foo . " XXX '" . (join $", @arr) . "'";
Todas las operaciones anteriores se realizan simultáneamente, de izquierda a derecha.
Debido a que el resultado de
"\Q CADENA \E"
tiene todos los metacaracteres entrecomillados, no hay forma de insertar un literal$
o@
dentro de una pareja\Q\E
. Si está protegido por un\
,$
se escapará para convertirse en"\\\$"
; si no, se interpreta como el inicio de un escalar interpolado.Tenga en cuenta también que el código de interpolación tiene que tomar una decisión sobre dónde termina el escalar interpolado. Por ejemplo,
"a $x -> {c}"
realmente significa:"a " . $x . " -> {c}";
o:
"a " . $x -> {c};
La mayoría de las veces, será el texto más largo posible que no incluya espacios entre los componentes y que contenga un juego de llaves o corchetes. Debido a que el resultado puede ser determinado por votación basada en estimadores heurísticos, el resultado no es estrictamente predecible. Afortunadamente, y por lo general, es correcto para los casos ambiguos.
- el reemplazo de
s///
-
El procesamiento de
\Q
,\U
,\u
,\L
,\l
,\F
y su interpolación ocurren como en las construccionesqq//
.Es en este paso que
\1
se convierte, de mala gana, en$1
en el texto de reemplazo des///
, con el fin de corregir a los incorregibles hackers de sed que todavía no han aprendido la correcta forma de indicar esta expresión. Se emite una advertencia si están activos el pragmause warnings
o la opción en línea de comandos -w (es decir, la variable$^W
). RE
en?RE?
,/RE/
,m/RE/
,s/RE/foo/
,-
El procesamiento de
\Q
,\U
,\u
,\L
,\l
,\F
,\E
y su interpolación ocurren (casi) como en las construccionesqq//
.El procesamiento de
\N{...}
también se hace aquí, y compilado en una forma intermedia para el compilador de expresiones regulares (RE). (Esto se debe a que, como se menciona más abajo, la compilación de expresiones regulares se puede hacer en tiempo de ejecución, y\N{...}
es una construcción en tiempo de compilación).No obstante, cualquier otra combinación de
\
seguida de un carácter no va a ser sustituida, sino sólo obviada, con el fin de analizarlas como expresiones regulares en el paso siguiente. Como\c
se omite en este paso,@
de\c@
en RE se trata, posiblemente, como un símbolo de array (por ejemplo@foo
), incluso aunque el mismo texto enqq//
sí da la interpolación de\c@
.Los bloques de código como
(?{BLOQUE})
se gestionan devolviendo temporalmente el control al intérprete de perl, de una forma similar a lo que sería la expresión con subíndices interpolados en un array, como lo sería en"foo$array[1+f("[xyz")]bar"
.Además, dentro de
(?{BLOQUE})
,(?# comentario )
, y un#
-comentario en una/x
-expresión regular, no se realiza ningún tipo de procesamiento. Este es el primer paso en el que la presencia del modificador/x
es relevante.La interpolación en los patrones tiene varias peculiaridades:
$|
,$(
,$)
,@+
y@-
no son interpoladas, y las construcciones$var[ALGO]
son promovidas (por varios estimadores diferentes) a ser un elemento de array o$var
seguida de una RE alternativa. Aquí es donde la notación${arr[$bar]}
es muy útil:/${arr[0-9]}/
se interpreta como un elemento de array-9
, no como una expresión regular desde la variable$arr
seguida por un dígito, que puede ser la interpretación de/$arr[0-9]/
. Debido a que la promoción puede ocurrir desde distintos estimadores, el resultado no es predecible.La falta de tratamiento de
\\
crea restricciones específicas en el pos-procesado del texto. Si el delimitador es/
, no se puede obtener la combinación\/
en el resultado de este paso./
terminará la expresión regular,\/
será reducido a/
en el paso anterior, y\\/
será mantenido tal cual. Dado que/
es equivalente a\/
dentro de una expresión regular, esto no importará a menos que el delimitador pase a ser un carácter especial para el motor de RE, como ens*foo*bar*
,m[foo]
, o?foo?
; o un carácter alfanumérico, como en:m m ^ a \s* b mmx;
En la RE anterior, que está intencionalmente ofuscada para su ilustración, el delimitador es
m
, el modificador esmx
, y después de la eliminación de los delimitadores, la RE es la misma quem/ ^ a \s* b /mx
. Hay más motivos que nos alientan para restringir sus delimitadores a elecciones no alfanuméricas ni espacios en blanco.
Este paso es el último para todas las construcciones, salvo las expresiones regulares, que son procesadas más adelante.
- analizar expresiones regulares
-
Se realizaron algunos pasos previos durante la compilación del código Perl, pero éste sucede en tiempo de ejecución, aunque puede ser optimizado para ser valorado en tiempo de compilación, si procede. Después del proceso previo descrito anteriormente, y posiblemente después de la evaluación, por si la concatenación, unión, traducción de tamaño de caja, o metaentrecomillado estuvieran involucradas, la cadena resultante es pasada al motor de RE para su compilación.
Pase lo que pase en el motor de RE podría estar mejor explicado en perlre, pero en aras de la continuidad, lo haremos aquí.
Este es otro paso donde la presencia del modificador
/x
es relevante. El motor de RE explora la cadena de izquierda a derecha y lo convierte en un autómata finito.Los caracteres escapados con una barra diagonal inversa son sustituidos por sus correspondientes cadenas de texto literales (como en
\{
), o sino generan nodos especiales en el autómata finito (como en\b
). Caracteres especiales al motor de RE (como|
) generan sus correspondientes nodos o grupos de nodos.(?#...)
los comentarios son ignorados. Todo lo demás es, o bien convertido en cadenas de literales para ser cotejados, o bien se ignora (como lo es el espacio en blanco y los comentarios#
, si/x
está presente).El análisis de la construcción clase de caracteres, entre corchetes,
[...]
, es bastante diferente a la regla utilizada para el resto del patrón. El terminador de esta construcción es encontrado usando las mismas reglas que para encontrar el terminador de la construcción delimitada por llaves,{}
, con la única excepción de que]
inmediatamente después de un[
se trata como si estuviera precedido por una barra diagonal inversa.El finalizador en tiempo de ejecución de
(?{...})
se encuentra cambiando temporalmente el control al intérprete de perl, que tendría parar en el punto donde se encuentra la}
que balancea la terminación lógica.Es posible inspeccionar tanto la cadena dada al motor RE y el autómata finito que resulta. Ver los argumentos
debug
/debugcolor
en el pragmause re
, así como la opción en línea de comandos de Perl -Dr documentado en "Opciones de comando" in perlrun. - Optimización de expresiones regulares
-
Este paso se describe aquí solo para completar la documentación. Ya que no cambia la semántica, los detalles de este paso no están documentados y están sujetas a cambios sin previo aviso. Este paso se realiza en el autómata finito que se generó durante la pasada anterior.
Es en esta etapa en que
split()
, silenciosamente, optimiza/^/
para que signifique/^/m
.
Operadores E/S
Hay varios operadores de E/S que debe conocer.
Una cadena delimitada por comillas simples invertidas (acentos graves) se somete a una primera interpolación de entrecomillado doble. Entonces se interpreta como un comando externo, y la salida de ese comando es el valor de la cadena entrecomillada, como en un shell. En contexto escalar, se devuelve una sola cadena consistente en toda la salida. En contexto de lista, se devuelve una lista de valores, uno por cada línea de la salida. (Puede configurar $/
para utilizar otro terminador de línea). El comando se ejecuta cada vez que el pseudo-literal se evalúa. El valor de estado del comando se devuelve en $?
(Vea perlvar para la interpretación del valor de $?
). A diferencia de csh, no se realiza traducción en el retorno de los datos: los caracteres de fin de línea siguen siendo caracteres de fin de línea. A diferencia de cualquiera de los shell, las comillas simples no impiden que los nombres de variables sean interpretadas, en el comando. Para pasar un signo de dólar literal al shell, necesita escaparlo con una barra diagonal inversa. La forma generalizada de las comillas invertidas es qx//
. (Debido a que las comillas invertidas siempre provocan una expansión a nivel de shell, vea perlsec para consultar los problemas de seguridad).
En contexto escalar, la evaluación de un identificador de archivo entre ángulos retorna la siguiente línea de ese archivo (con el carácter de salto de línea, en su caso, incluido), o undef
al final del archivo o en caso de error. Cuando $/
está configurado a undef
(a veces conocido como modo sorber-el-archivo) y el archivo está vacío, devuelve ''
la primera vez, seguido, posteriormente, por un undef
.
Normalmente debe asignar el valor devuelto a una variable, pero hay una situación en la que sucede una asignación automática. Si y sólo si el símbolo de entrada es la única cosa dentro de la condición de una instrucción while
(incluso si está disfrazado como un bucle for(;;)
), el valor se asigna automáticamente a la variable global $_
, destruyendo su valor anterior. (Esto puede parecer algo extraño para usted, pero usará esta construcción en casi todos los scripts de Perl que escriba). La variable $_
no está, implícitamente, localizada. Tendrá que poner un local $_;
antes del bucle si quiere que sea así.
Las siguientes líneas son equivalentes:
while (defined($_ = <STDIN>)) { print; }
while ($_ = <STDIN>) { print; }
while (<STDIN>) { print; }
for (;<STDIN>;) { print; }
print while defined($_ = <STDIN>);
print while ($_ = <STDIN>);
print while <STDIN>;
Esto también se comporta de manera similar, pero asigna a una variable léxica en lugar de a $_
:
while (my $linea = <STDIN>) { print $linea }
En estas construcciones de bucle, el valor asignado (tanto si la asignación es automática o explícita) es examinado para ver si está definido. La prueba de definición evita problemas donde la línea contiene un valor de cadena que sería tratado como falso por Perl; por ejemplo, un "" o un "0"
sin un carácter de final de línea. Si realmente quiere mirar por esos valores para terminar el bucle, debe hacerse la prueba de forma explícita:
while (($_ = <STDIN>) ne '0') { ... }
while (<STDIN>) { last unless $_; ... }
En otros contextos booleanos, <IDENTIFICADOR_ARCHIVO>
sin una prueba explícita de defined
o comparación, provoca una advertencia si está en vigor el pragma use warnings
o la opción -w en la línea de comandos (la variable $^W
).
Los identificadores de archivo STDIN, STDOUT y STDERR están predefinidos. (Los identificadores de archivo stdin
, stdout
, y stderr
también funcionarán, excepto en paquetes en los que podrían ser interpretados como identificadores locales en lugar de globales). Se pueden crear identificadores de archivo adicionales con la función open()
, entre otros. Vea perlopentut y "open" in perlfunc para más detalles sobre esto.
Si un <IDENTIFICADOR_ARCHIVO>
se utiliza en un contexto en el que está esperando una lista, se devuelve una lista que contiene todas las líneas de entrada, una línea por cada elemento de la lista. De esta manera, es fácil que el espacio ocupado por los datos crezca a un gran tamaño, así que tenga cuidado.
<IDENTIFICADOR_ARCHIVO>
también se puede escribir como readline(*IDENTIFICADOR_ARCHIVO)
. Vea "readline" in perlfunc.
El identificador de archivo nulo <>
es especial: se puede utilizar para emular el comportamiento de sed y awk, y cualquier otro programa de filtrado Unix que tome una lista de nombres de archivo, haciendo lo mismo en cada línea de la entrada para todos ellos. La entrada desde <>
puede venir, ya sea desde la entrada estándar, o de cada archivo listado en la línea de comandos. He aquí cómo funciona: la primera vez que <>
se evalúa, se comprueba el array @ARGV
, y si está vacío, $ARGV[0]
se configura a "-"
, que cuando se abra le ofrecerá a usted la entrada estándar. Luego, el array @ARGV
se procesa como una lista de nombres de archivo. El bucle
while (<>) {
... # código por cada línea
}
es equivalente al siguiente pseudo código Perl:
unshift(@ARGV, '-') unless @ARGV;
while ($ARGV = shift) {
open(ARGV, $ARGV);
while (<ARGV>) {
... # código por cada línea
}
}
excepto que no es tan complicado como hemos dicho, y realmente funcionará. Realmente, desplaza el array @ARGV
y pone el nombre del archivo actual en la variable $ARGV
. Internamente, también utiliza el identificador de archivo <ARGV>. <>
es, justamente, un sinónimo de <ARGV>
, lo cual es mágico. (El pseudo código anterior no funciona porque trata a <ARGV>
como no mágico).
Dado que el identificador de archivo nulo utiliza el formato de dos argumentos de "open" in perlfunc, interpreta los caracteres especiales, así que si tiene un script como este:
while (<>) {
print;
}
y lo llama con perl peligroso.pl 'rm -rfv *|'
, lo que realmente hace es abrir una tubería, ejecutar el comando rm
y leer la salida de rm
desde esa tubería. Si desea que todos los elementos de @ARGV
deben ser interpretados como nombres de archivo, puede utilizar el módulo ARGV::readonly
de CPAN, o usar el doble diamante:
while (<<>>) {
print;
}
Usando el doble diamante dentro de un while() hace que el open() use la forma de tres argumentos (con el segundo argumento comenzando por <
), así que todos los argumentos en ARGV
se tratan como nombres de archivo literales (incluyendo "-"
). (Note que, por comodidad, si usa <<>>
y si @ARGV
está vacío, seguirá leyendo desde la entrada estándar).
Puede modificar @ARGV
antes del primer <>
siempre que el array termine conteniendo la lista de nombres de archivos que realmente quiere. Los números de línea ($.
) continuarán como si la entrada fuese un único archivo. Vea el ejemplo en "eof" in perlfunc de cómo restablecer los números de línea en cada archivo.
Si desea establecer @ARGV
a su propia lista de archivos, adelante. Lo siguiente establecerá @ARGV
a todos los archivos de texto plano, si no se inicializó @ARGV
:
@ARGV = grep { -f && -T } glob('*') unless @ARGV;
Incluso se puede configurar para entubar a comandos. Por ejemplo, esto filtrará automáticamente los argumentos comprimidos a través de gzip:
@ARGV = map { /\.(gz|Z)$/ ? "gzip -dc < $_ |" : $_ } @ARGV;
Si desea pasar opciones en su programa, puede utilizar uno de los módulos Getopts
o poner un bucle, al principio, de esta manera:
while ($_ = $ARGV[0], /^-/) {
shift;
last if /^--$/;
if (/^-D(.*)/) { $debug = $1 }
if (/^-v/) { $verboso++ }
# ... # otras opciones
}
while (<>) {
# ... # código por cada línea
}
El símbolo <>
devolverá undef
para el fin-de-archivo solo una vez. Si más tarde lo vuelve a llamar, asumirá que está procesando otra lista @ARGV
, y si no ha establecido @ARGV
, leerá la entrada desde STDIN.
Si lo que los ángulos contienen es una variable escalar simple (por ejemplo, $foo
), entonces esa variable contiene el nombre del identificador de archivo desde el qué recibir la entrada, o su typeglob, o una referencia al mismo. Por ejemplo:
$fh = \*STDIN;
$linea = <$fh>;
Si lo que está dentro de los ángulos no es ni un identificador de archivo ni una variable escalar simple que contenga un nombre de identificador de archivo, typeglob, o referencia a typeglob, se interpreta como un patrón de nombre de archivo para ser expandido, y será devuelta la lista de nombres de archivo o el siguiente nombre de archivo de la lista, dependiendo del contexto. Esta distinción está determinada sólo por razones sintácticas. Esto significa que <$x>
siempre es un readline()
de un identificador de archivo indirecto, pero <$hash{clave}>
siempre es un glob()
. Esto se debe a que $x
es una variable escalar simple, pero $hash{clave}
no lo es: es un elemento de un hash. Incluso <$x >
(note el espacio extra) es tratado como glob("$x ")
, no como readline($x)
.
Se hace en primer lugar una interpretación al estilo de las comillas dobles, pero no puede escribir <$foo>
porque eso es un identificador de archivo indirecto, como se ha explicado en el párrafo anterior. (En versiones anteriores de Perl, los programadores insertaban llaves para forzar la interpretación como una expansión de nombre de archivo: <$foo{}>
. En estos días, se considera más limpio llamar a la función interna directamente, como en glob($foo)
, que es probablemente la forma correcta de haberlo hecho desde el principio). Por ejemplo:
while (<*.c>) {
chmod 0644, $_;
}
es casi equivalente a:
open(FOO, "echo *.c | tr -s ' \t\r\f' '\\012\\012\\012\\012'|");
while (<FOO>) {
chomp;
chmod 0644, $_;
}
salvo que la expansión realmente se hace internamente usando la extensión estándar File::Glob
. Por supuesto, el camino más corto para hacer lo anterior es:
chmod 0644, <*.c>;
Una expansión evalúa sus argumentos (incorporados) sólo cuando está iniciando una nueva lista. Todos los valores deben leerse antes de empezar de nuevo. En contexto de lista, esto no es importante, ya que, de todos modos, los obtiene automáticamente. Sin embargo, en contexto escalar el operador devuelve el siguiente valor cada vez que se le llama, o undef
cuando la lista se ha agotado. Al igual que cuando un identificador de archivo lee, un defined
es generado cuando la expansión se produce en la parte de prueba de un while
, porque una expansión legal así lo devuelve (por ejemplo, un archivo llamado 0), o de otra manera, terminaría el bucle. Una vez más, undef
sólo se devuelve una vez. Así que si está esperando un único valor de una expansión, es mucho mejor escribir
($archivo) = <loquesea*>;
que
$archivo = <loquesea*>;
ya que este último alternará entre devolver un nombre de archivo y devolver falso.
Si está tratando de hacer interpolación de variables, sin duda es mejor utilizar la función glob()
, porque la notación más antigua puede hacer que las personas se confundan con la notación de identificador de archivo indirecto.
@archivos = glob("$dir/*.[ch]");
@archivos = glob($archivos[$i]);
Plegado de constantes
Al igual que C, Perl hace una cierta cantidad de evaluación de expresiones en tiempo de compilación cuando determina que todos los argumentos a un operador son estáticos y no tienen efectos secundarios. En particular, concatenación de cadenas que sucede en tiempo de compilación entre literales que no hacen sustitución de variables. La interpolación con barras diagonales inversas también sucede en tiempo de compilación. Se puede decir
'Ahora es el momento para todos'
. "\n"
. 'los hombres buenos por venir.'
y todo esto se reduce a una sola cadena, internamente. Del mismo modo, si dice
foreach $archivo (@archivos) {
if (-s $archivo > 5 + 100 * 2**16) { }
}
el compilador precalcula el número que representa esa expresión para que el intérprete no tenga que hacerlo.
No-operaciones
Perl, oficialmente, no tiene un operador de no-operación, pero las constantes simples 0
y 1
son un caso especial, que no producen una advertencia en un contexto vacío, por lo que puede, por ejemplo, hacer de forma segura
1 while foo();
Operadores de bit en cadenas
Cadenas de bits de cualquier tamaño pueden manipularse por los operadores binarios (~ | & ^
).
Si los operandos a una operación bit a bit binaria son cadenas de diferentes tamaños, los operadores | y ^ actúan como si el operando más corto tuviera más bits cero a la derecha, mientras que el operador & actúa como si el operando más largo fuera truncado a la longitud de la menor. La granularidad para dicha extensión o truncamiento es de uno o más bytes.
# Ejemplo basados en ASCII
print "j p \n" ^ " a h"; # imprime "JAPH\n"
print "JA" | " ph\n"; # imprime "japh\n"
print "japh\nJunk" & '_____'; # imprime "JAPH\n";
print 'p N$' ^ " E<H\n"; # imprime "Perl\n";
Si tiene la intención de manipular cadenas de bits, asegúrese de que está suministrando cadenas de bits: si un operando es un número, esto implicará una operación binaria numérica bit a bit. Puede indicar, explícitamente, el tipo de operación que desea realizar utilizando ""
o 0+
, como en los ejemplos siguientes.
$foo = 150 | 105; # produce 255 (0x96 | 0x69 es 0xFF)
$foo = '150' | 105; # produce 255
$foo = 150 | '105'; # produce 255
$foo = '150' | '105'; # produce la cadena '155' (bajo ASCII)
$baz = 0+$foo & 0+$bar; # ambas op. explícitamente numéricas
$biz = "$foo" ^ "$bar"; # ambas op. explícitamente como literales
Este, comportamiento un poco impredecible se puede evitar con la característica experimental "bitwise", nueva en Perl 5.22. Puede activarlo con use feature 'bitwise'
. Por defecto, lo advertirá a menos que se desactive la categoría de advertencias "experimental::bitwise"
. (use experimental 'bitwise'
activará la característica y desactivará la advertencia). Con esta característica, los cuatro operadores de bit estándar (~ | & ^
) son siempre numéricos. Añadiendo un punto a cada operador (~. |. &. ^.
) fuerza a tratar a los operandos como cadenas de caracteres:
use experimental "bitwise";
$foo = 150 | 105; # produce 255 (0x96 | 0x69 es 0xFF)
$foo = '150' | 105; # produce 255
$foo = 150 | '105'; # produce 255
$foo = '150' | '105'; # produce 255
$foo = 150 |. 105; # produce la cadena '155'
$foo = '150' |. 105; # produce la cadena '155'
$foo = 150 |.'105'; # produce la cadena '155'
$foo = '150' |.'105'; # produce la cadena '155'
$baz = $foo & $bar; # ambos operandos numéricos
$biz = $foo ^. $bar; # ambos operandos convertidos a cadenas
Las variantes de asignación de estos operadores (&= |= ^= &.= |.= ^.=
) se comportan igual con la nueva característica.
El comportamiento de estos operadores es problemático (y sujeto a cambio) si alguna o ambas de las cadenas se codifican en UTF-8 (vea "Semánticas de bytes y caracteres" in perlunicode.
Vea "vec" in perlfunc para obtener información sobre cómo manipular bits individuales de un vector de bits.
Aritmética entera
De forma predeterminada, Perl se supone que debe hacer la mayor parte de su aritmética en punto flotante. Pero al decir
use integer;
puede indicar al compilador que utilice operaciones con enteros (vea integer para una explicación más detallada) desde aquí hasta el final del BLOQUE actual. Un BLOQUE interno puede revocar esto diciendo
no integer;
que durará hasta el final de ese BLOQUE. Tenga en cuenta que esto no significa que todo sea un número entero, sino simplemente que Perl utilizará operaciones de enteros para los operadores aritméticos, de comparación y de operaciones con bits. Por ejemplo, incluso bajo use integer
, si escribe sqrt(2)
, seguirá obteniendo, más o menos, 1.4142135623731
.
Utilizados en números, los operadores de bits (&
|
^
~
<<
>>
) siempre producen resultados enteros. (Pero vea también "Operadores de bit en cadenas"). Sin embargo, use integer
todavía tiene sentido para ellos. De forma predeterminada, los resultados se interpretan como enteros sin signo, pero si use integer
está en activo, sus resultados se interpretan como enteros con signo. Por ejemplo, ~0
por lo general se evalúa como un valor entero de gran tamaño. Sin embargo, use integer; ~0
es -1
en las máquinas con complemento a dos.
Aritmética de Punto Flotante
Mientras que use integer
sólo proporciona aritmética de enteros, no existe un mecanismo análogo para proporcionar redondeo automático o truncamiento a un determinado número de decimales. Para redondear a un determinado número de dígitos, sprintf()
o printf()
suele ser el camino más fácil. Vea perlfaq4.
Números de punto flotante son sólo aproximaciones a lo que un matemático llamaría a los números reales. Hay infinitamente más reales que flotantes, por lo que algunos detalles deben ser tenidos en cuenta. Por ejemplo:
printf "%.20g\n", 123456789123456789;
# produce 123456789123456784
No es una buena idea comprobar la igualdad o la desigualdad exacta de números en punto flotante. Aquí hay un (relativamente caro) ejemplo en torno a cómo comprobar si dos números de punto flotante son iguales en un determinado número de decimales. Ver Knuth, volumen II, para un tratamiento más fuerte de este tema.
sub fp_igual {
my ($X, $Y, $PUNTOS) = @_;
my ($tX, $tY);
$tX = sprintf("%.${PUNTOS}g", $X);
$tY = sprintf("%.${PUNTOS}g", $Y);
return $tX eq $tY;
}
El módulo POSIX (parte de la distribución estándar de Perl) implementa ceil()
, floor()
, y otras funciones matemáticas y trigonométricas. El módulo Math::Complex
(parte de la distribución estándar de Perl) define funciones matemáticas que funcionan tanto para reales como números imaginarios. Math::Complex
no es tan eficiente como POSIX, pero POSIX no puede trabajar con números complejos.
El redondeo en las aplicaciones financieras puede tener consecuencias graves, y el método de redondeo utilizado debe ser descrito con precisión. En estos casos, es mejor no confiar en el sistema de redondeo que está utilizando Perl, sino que en su lugar deba implementar la función de redondeo que necesite.
Grandes números
Los módulos estándares Math::BigInt
, Math::BigRat
, y Math::BigFloat
, junto con los pragmas bignum
, bigint
y bigrat
, proporcionan aritmética de precisión variable y sobrecarga de operadores, aunque en la actualidad, son bastante lentos. A costa de algún espacio y velocidad, evitan los peligros asociados a la limitada precisión de las representaciones.
use 5.010;
use bigint; # interfaz sencillo para Math::BigInt
$x = 123456789123456789;
say $x * $x;
+15241578780673678515622620750190521
O con números racionales:
use 5.010;
use bigrat;
$x = 3/22;
$y = 4/6;
say "x/y is ", $x/$y;
say "x*y is ", $x*$y;
x/y is 9/44
x*y is 1/11
Algunos módulos le permiten hacer cálculos con precisión ilimitada o fija (limitado solo por la memoria y tiempo de CPU). También hay algunos módulos no estándares que ofrecen implementaciones más rápidas a través de bibliotecas de C externas.
Aquí hay un breve resumen, aunque incompleto:
Math::String trata secuencias de cadenas como números
Math::FixedPrecision calcula con una precisión fija
Math::Currency para cálculos monetarios
Bit::Vector manipula vectores bit rápidamente (usa C)
Math::BigIntFast envoltorio de Bit::Vector para grandes números
Math::Pari ofrece acceso a la biblioteca Pari, en C
Math::Cephes usa la biblioteca externa en C Cephes (no
para grandes números)
Math::Cephes::Fraction fracciones vía la biblioteca Cephes
Math::GMP otro usando una biblioteca C externa
Math::GMPz una interfaz alternativa a los grandes int de libgmp
Math::GMPq una interfaz a los números fraccionarios de libgmp
Math::GMPf una interfaz a los números en punto flotante de libgmp
Elija con cuidado.
TRADUCTORES
Joaquín Ferrero (Tech Lead)
Enrique Nell (Language Lead)