Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
tree: 888b4cb659
Fetching contributors…

Cannot retrieve contributors at this time

2215 lines (1455 sloc) 143.109 kb

NAME

perlop - Operadores y precedencia en Perl

DESCRIPCIÓN

Precedencia de operadores y asociatividad

Precedencia de operadores y asociatividad funciona en Perl más o menos como se hace en matemáticas.

Precedencia de operadores significa que algunos operadores son evaluados antes que otros. Por ejemplo, en 2 + 4 * 5, la multiplicación tiene una precedencia mayor por lo que 4 * 5 es evaluado primero, resultando 2 + 20 == 22 y no 6 * 5 == 30.

Asociatividad de operadores define qué sucede si una secuencia de los mismos operadores es usada una detrás de otra: 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 es evaluada 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 listas (por la izquierda)
    izquierda   ->
    no asoc.    ++ --
    derecha     **
    right       ! ~ \ 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     ?:
    derecha     = += -= *= etc.
    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 listas (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 otro operador unario (chdir(), etc) es seguido por un paréntesis de apertura como el siguiente símbolo, 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 son evaluadas antes que el sort, pero 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 actuar como un simple 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 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";

probablemente no hace lo que usted espera, a primera vista. Los paréntesis encierran la lista de argumentos para print que se evalúa (imprimir el resultado de $foo & 255). Entonces uno es añadido 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 son analizados 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.

Auto incremento y auto decremento

"++" y "--" funcionan como en C. Es decir, si son colocados antes de una variable, incrementan o decrementan la variable por uno 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 cuando 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 tiene un poco más de magia en él. 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 del C pow(3), que en realidad trabaja internamente con dobles).

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 string que se parezca a un número. Si el operando es un identificador, es devuelta un string formado por un signo menos concatenado con el identificador. De otra manera, si el string comienza con un signo más o un menos, se devuelve un string que comience con el signo opuesto. Uno de los efectos de estas reglas es -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.

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

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. Ver "Operadores Regexp 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 va generar un error de sintaxis.

Binario "!~" es justo como "=~" excepto que el valor de retorno es negado, en el sentido lógico.

Binario "!~" con una sustitución no destructiva (s///r) o transliteración (y///r) es un error sintáctico.

Operadores multiplicativos

Binario "*" multiplica dos números.

Binario "/" divide dos números.

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 $a y $b: si $b es positivo, entonces $a % $b es $a menos el mayor múltiplo de $b menor o igual a $a. Si $b es negativo, entonces $a % $b es $a menos el múltiplo más pequeño de $b que no es menor que $a (es decir, el resultado será menor o igual a cero). Si los operandos $a y $b son valores en punto flotante y el valor absoluto de $b (es decir, abs($b)) es menor que (UV_MAX + 1), solo la porción de entero de $a y $b será usada 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($b)) es mayor o igual a (UV_MAX + 1), "%" computa el resto en punto flotante $r en la ecuación ($r = $a - $i*$b) donde $i es un cierto entero que hace que $r tenga el mismo signo que el operando de la derecha $b (no como el operando izquierdo $a como la función C fmod()) y el valor absoluto menor que el de $b. Tenga en cuenta que cuando use integer está en su ámbito, "%" le da acceso directo al operador módulo, implementado por su compilador de C. Este operador no está tan bien definido para operandos negativos, pero se ejecutará más rápido.

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, 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

Binario + devuelve la suma de dos números.

Binario - devuelve la diferencia de dos números.

Binario . concatena dos cadenas.

Operadores de desplazamiento

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. (Ver también "Aritmética entera").

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. (Ver también "Aritmética entera").

Tenga en cuenta que tanto << como >>, en Perl, están implementados directamente a través de << y >> en C. Si use integer (vea "Aritmética entera") está en vigor entonces se utilizan los enteros C con signo; sino, se utilizan enteros C sin signo. De cualquier manera, la aplicación no va a generar resultados más grandes que el tamaño del tipo entero con el que Perl fue construido (32 o 64 bits).

El resultado del desbordamiento del rango de los números enteros no está definido, ya que tampoco está definido en C. En otras palabras, usando enteros de 32 bits, 1 << 32 no está definido. Desplazando por un número negativo de bits también está indefinido.

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 son tratados como funciones con un argumento, con paréntesis opcionales.

Si cualquier operador de lista (print(), etc) o cualquier otro operador unario (chdir(), etc) es seguido por un paréntesis de apertura como el siguiente símbolo, 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 test de archivos, como -f, -M, etc, son tratados 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 "$file.bak".

Vea también "Términos y Operadores de listas (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á exento de advertencias acerca de conversiones numéricas impropias, al igual que "0 pero verdadero".

Binario "<" devuelve verdadero si el argumento de la izquierda es numéricamente menor que el argumento de la derecha.

Binario ">" devuelve verdadero si el argumento de la izquierda es numéricamente mayor que el argumento de la derecha.

Binario "<=" devuelve verdadero si el argumento de la izquierda es numéricamente menor o igual que el argumento de la derecha.

Binario ">=" devuelve verdadero si el argumento de la izquierda es numéricamente mayor o igual que el argumento de la derecha.

Binario "lt" devuelve verdadero si el argumento de la izquierda es alfanuméricamente menor que el argumento de la derecha.

Binario "gt" devuelve verdadero si el argumento de la izquierda es alfanuméricamente mayor que el argumento de la derecha.

Binario "le" devuelve verdadero si el argumento de la izquierda es alfanuméricamente menor o igual que el argumento de la derecha.

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

Binario "==" devuelve verdadero si el argumento de la izquierda es numéricamente igual que el argumento de la derecha.

Binario "!=" devuelve verdadero si el argumento de la izquierda es numéricamente distinto que el argumento de la derecha.

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 es compatible con NaN (not-anumbers, 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 es compatible con NaN entonces NaN es sólo una cadena con un valor numérico 0.

    $ perl -le '$a = "NaN"; print "No hay soporte para NaN" if $a == $a'
    $ perl -le '$a = "NaN"; print "Hay soporte para NaN" if $a != $a'

(Tenga en cuenta que los pragmas bigint, bigrat, y bignum soportan "NaN").

Binario "eq" devuelve verdadero si el argumento de la izquierda es alfanuméricamente igual que el argumento de la derecha.

Binario "ne" devuelve verdadero si el argumento de la izquierda es alfanuméricamente distinto que el argumento de la derecha.

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.

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 si un anterior use locale (pero no use locale ':not_characters') está en vigor. Vea perllocale. No los mezcle con Unicode, sólo con codificaciones binarias antiguas. Los módulos estándares Unicode::Collate y Unicode::Collate::Locale ofrecen soluciones mucho más poderosas a los problemas de cotejo.

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.

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 actuales 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 actuales (numérico, cadena, matriz, hash, etc.). Al igual que los operadores de igualdad con los que comparte la misma prioridad, ~~ 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 de un 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
 Regexp        ARRAY       cualquier elemento de ARRAY que coincida con el patrón Regexp
                igual que: grep { /Regexp/ } 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       todas y las mismas claves en ambos HASHes
                igual que: keys HASH1 ==
                         grep { exists HASH2->{$_} } keys HASH1
 ARRAY         HASH        cualquier elemento de ARRAY que existe como clave del HASH
                igual que: grep { exists HASH->{$_} } ARRAY
 Regexp        HASH        cualquier clave del HASH que coincida con el patrón Regexp
                igual que: grep { /Regexp/ } 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 Regexp:

 Izquierdo     Derecho     Descripción y pseudocódigo                               
 ===============================================================
 ARRAY         Regexp      cualquier elemento de ARRAY que coincida con Regexp
                igual que: grep { /Regexp/ } ARRAY
 HASH          Regexp      cualquier elemento de HASH que coincida con Regexp
                igual que: grep { /Regexp/ } keys HASH
 Cualquiera    Regexp      coincidencia
                igual que: Cualquiera =~ /Regexp/

 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
 Número        numeral[4]  igualdad numérica
                 igual que: Número == numeral
 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.

La entrada del código "igual que" no siempre es una interpretación exacta. 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, morado => 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 "pequeno 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 este ejemplo muestra:

    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 de 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 uno 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) tiene un 4 en ella.

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) nombre, rango, y número de serie"
            unless $inic_campos ~~ $CAMPOS_REQUERIDOS;

        ...
    }

o, si se permiten otros campos no obligatorios, use ARRAY ~~ HASH:

    use v5.10.1;
    sub make_dogtag {
        state $CAMPOS_REQUERIDOS = { nombre=>1, rango=>1, num_serie=>1 };

        my ($clase, $inic_campos) = @_;

        die "Debe indicar (al menos) nombre, rango, y número de serie"
            unless [keys %{$inic_campos}] ~~ $CAMPOS_REQUERIDOS;

        ...
    }

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 manejador huele a IO (pero, por favor, ¡no haga esto!):

    use IO::Handle;
    my $fh = IO::Handle->new();
    if ($fh ~~ /\bIO\b/) {
        say "el manejador 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

Binario "&" devuelve la operación AND, bit a bit, de sus operandos. (Vea también "Aritmética entera" y "Operadores de bit en cadenas").

Tenga en cuenta que "&" tiene una menor prioridad que los operadores relaciones, así que, por ejemplo, los paréntesis son esenciales en una prueba como

    print "Par\n" if ($x & 1) == 0;

Or y exclusivo or binarios

Binario "|" devuelve la operación OR, bit a bit, de sus operandos. (Vea también "Aritmética entera" y "Operadores de bit en cadenas").

Binario "^" devuelve la operación XOR, bit a bit, de sus operandos. (Vea también "Aritmética entera" y "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;

And lógico al estilo del C

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 es evaluado.

Or lógico al estilo del C

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 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, es devuelto 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 el operador ternario puede ser utilizado como un valor a la izquierda, mientras que EXPR1 // EXPR2, no puede). Esto es muy útil para proporcionar valores por defecto a las variables. Si realmente desea probar si al menos uno de los dos, $a o $b, están definidos, use defined($a // $b).

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 el 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 es un error
    @a = scalar(@b) || @c;      # quiere realmente 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 usted puede usarlos con seguridad después de un operador de lista sin necesidad de 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 adelante.

Operadores de rango

Binario ".." es el operador rango, que en realidad son dos operadores diferentes en función 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, ver abajo.

En contexto 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 algo para poder buscar si desea excluir el punto final. 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, este operando es considerado cierto si es igual (==) al número de línea actual de la entrada (la variable $.).

Para ser 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 de un archivo. Por otra parte, "span" .. "spat" oo 2.18 .. 3,14 no harán lo que quiere hacer en contexto escalar porque cada uno de los operandos son evaluados utilizando su representación entera.

Ejemplos:

Como operador escalar:

    if (101 .. 200) { print; } # imprime las segundas cien líneas,
                               # versión corta de ($. == 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 como 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 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 operadores 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, porque existen muchos otros caracteres griegos en minúscula que estos, para buscar por caracteres griegos en minúscula en una expresión regular, se utiliza el patrón /(?:(?=\p{Greek})\p{Lower})+/.

Debido a que cada operando es evaluado 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

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.

    $a = $ok ? $b : $c;  # obtiene un escalar
    @a = $ok ? @b : @c;  # obtiene un array
    $a = $ok ? @b : @c;  # oops, ¡esto solo cuenta elementos!

El operador puede ser asignado si tanto el segundo y tercer argumentos son ivalores legales (lo que significa que les puede asignar valores):

    ($a_o_b ? $a : $b) = $c;

Debido a que este operador produce un resultado asignable, usar asignaciones sin paréntesis hará que se meta en problemas. Por ejemplo, esto:

    $a % 2 ? $a += 10 : $a += 2

En realidad significa lo siguiente:

    (($a % 2) ? ($a += 10) : $a) += 2

En lugar de esto:

    ($a % 2) ? ($a += 10) : ($a += 2)

Esto, probablemente, se debe escribir más sencillamente como:

    $a += ($a % 2) ? 10 : 2;

Operadores de asignación

"=" es el operador ordinario de asignación.

Operadores de asignación funcionan como en C. Es decir,

    $a += 2;

es equivalente a

    $a = $a + 2;

pero sin duplicar los efectos laterales que, desreferenciando el valor de la 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.

A diferencia de C, el operador de asignación escalar produce un ivalor válido. Modificando una asignación es equivalente a realizar la asignación y luego modificando 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,

    ($a += 2) *= 3;

es equivalente a

    $a += 2;
    $a *= 3;

Del mismo modo, una asignación de lista en contexto de lista produce la lista de ivalores 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.

Operador coma

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 => es un sinónimo de la coma, salvo que causa que su operando de la izquierda debe 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 pueden ser utilizados 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 ser que también acabe 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 listas (por la izquierda)".

Not lógico

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

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

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:

    $a = $b or $c;              # error: esto está mal
    ($a = $b) or $c;            # en realidad significa esto
    $a = $b || $c;              # mejor escrito de esta manera

Sin embargo, cuando se trata de una asignación en contexto de lista y usted 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 tiene C pero Perl no:

unario &

Operador Dirección-de. (Vea, sin embargo, el operador "\" para tomar una referencia).

unario *

Operador de Desreferencia. (Los operadores de desreferencia de Perl están tipificados: $, @, %, y &).

(TYPE)

Operador de Forzado de tipo.

Comillas y Operadores de comillas

Mientras solemos 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-empotrado         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($a eq "}") ... }; # MAL

es un error de sintaxis. El módulo Text::Balanced (estándar a partir de v5.8, y desde CPAN antes de esa fecha) 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# es analizado 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. o secuencia car. Unicode
    \N{U+263D}  [4,8]   Carácter Unicode               (ejemplo: FIRST QUARTER MOON)
    \c[         [5]     car. control                    (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. Ver "[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. Ver "[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 será interpretado como \x07, y un único \x será interpretado 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 punto 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)
   \c]      chr(29)
   \c^      chr(30)
   \c?      chr(127)

En otras palabras, es el carácter cuyo código de punto era 64 xor con su mayúscula. \c? es DELETE porque ord("?") ^ 64 es 127, y \c@ es NULL porque el ord de "@" es 64, por lo que haciendo el xor 64 produce un 0.

Además, \c\X es igual a chr(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 estaría 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; ver "DIFERENCIAS EN LOS OPERADORES" in perlebcdic para ver la lista completa del significado de estas secuencias, tanto en las plataformas ASCII como en EBCDIC.

No se recomienda el uso de cualquier otro carácter después de la "c", aparte de los mencionados anteriormente, y algunos de ellos están en desuso, con la intención de eliminarlas en una posterior versión de Perl. Sin embargo, lo que le sucede ahora, para cualquiera de estos otros caracteres, es que el valor se obtiene haciendo un xor con el séptimo bit, que es 64.

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. Ver "[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, ver 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 \o{}, o convertirlo a otra cosa, como por ejemplo, a hexadecimal y usar en su lugar \x{}.

Tener menos de 3 dígitos puede dar lugar a un mensaje de advertencia engañoso, que dice que lo que sigue es ignorado. Por ejemplo, "\128" en el juego de caracteres ASCII es equivalente a los dos caracteres "\n8", pero se mostrará la advertencia Illegal octal digit '8' ignored (Se ignora el carácter octal ilegal '8'). Si lo que quiere es "\n8", puede evitar la aparición de esta advertencia rellenando su número octal con ceros: "\0128".

[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 "&". \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 no importa qué codificación nativa sea. El nombre del carácter en la posición 256º (empezando en 0) en Unicode es LATIN CAPITAL LETTER A WITH MACRON.

Hay un par de excepciones a la regla anterior. \N{U+número hex.} siempre es interpretado como un punto de código Unicode, por lo que \N{U+0050} es "P" incluso en plataformas EBCDIC. Y si use encoding está activo, el número es considerado que está en esa codificación, y es traducido en la codificación nativa de la plataforma si existe un carácter local correspondiente; de lo contrario, es traducido a Unicode.

NOTA: A diferencia de C y otros lenguajes, Perl no tiene una secuencia de escape \v para el tabulado vertical (VT - ASCII 11), pero puede usar \ck 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!) solo 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          escapa (desactiva) los metacaracteres de patrón hasta \E o
                fin 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 use locale está en vigor (pero no use locale ':not_characters'), el mapeo de tamaños de caja usado por \l, \L, \u y \U es tomado de la configuración regional actual. Ver perllocale. Si se usa Unicode (por ejemplo, \N{} o códigos de punto de 0x100 o superiores), el mapeo de tamaño de caja usado por \l, \L, \u y \U está definido por Unicode. Esto significa que el mapeo de un único carácter a veces puede producir varios caracteres. Bajo use locale, \F produce los mismos resultados que \L.

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 terminador de línea, la impresión de un "\n" puede no emitir ningún dato. 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 metes 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.

Interpolando un array o una parte de él, es interpolar los elementos por orden, separándolos por el valor de $", que es equivalente a 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 son interpoladas, así las expresiones regulares pueden ser incorporadas en patrones desde las variables. Si no es esto lo que quiere, 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 Regexp entrecomillados

Aquí están los operadores, parecidos a los de entrecomillado, que se aplican a las actividades relacionadas con la coincidencia.

qr/CADENA/msixpodual

Este operador entrecomilla (y posiblemente compila) CADENA como una expresión regular. CADENA es interpolada 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/msixpodual. 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, desreferenciándola 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 ser utilizado como un sub-patrón en una coincidencia:

    $re = qr/$patron/;
    $cadena =~ /foo${re}bar/;   # puede ser interpolado en otros patrones
    $cadena =~ $re;             # o usar 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(), usarlo puede tener ventajas de velocidad en algunas situaciones, notablemente si el resultado de qr() 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 una coincidencia de /$pat/ sea intentada. (Perl tiene otras muchas optimizaciones internas, pero ninguna será activada en el ejemplo anterior si no usamos el operador qr()).

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 serán definidas ${^PREMATCH}, ${^MATCH} y ${^POSTMATCH}.
    o   Compila el patrón solo una vez.
    a   ASCII-restrictivo: Use ASCII para \d, \s, \w; especificando dos "a"
        restringe aún más la concordancia de /i por lo que ningún carácter ASCII
        coincidirá con ningún carácter que no sea ASCII
    l   Usa la definición regional local (I<locale>)
    u   Usa las reglas Unicode
    d   Usa conjunto de caracteres Unicode o nativo, como en 5.12 y anteriores

Si un patrón precompilado se incrusta en un patrón más grande entonces los efectos de 'msixpluad' serán propagados apropiadamente. El efecto del modificador "o" no es propagado, 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 semánticas del juego de caracteres, pero /a es el único que querrá especificar explícitamente; los otros tres son seleccionados automáticamente por medio de diversos pragmas.

Ver 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 siguiente sección.

m/PATRÓN/msixpodualgc
/PATRÓN/msixpodualgc

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 vía los operadores =~ o !~, se busca en la cadena $_. (La cadena especificada con =~ no tiene por qué ser un valor a la 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 esta activa.

Si "/" es el delimitador entonces la inicial m es opcional. Con la m puede usar cualquier par de caracteres no-blancos (ASCII) como delimitadores. Esto es particularmente útil para hacer coincidir 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, descrito más abajo, en ?PATRÓN?. Si "'" "es el delimitador, no se realiza interpolación en el PATRÓN. Cuando se utiliza un carácter válido en un identificador, se requiere espacios en blanco después de la m.

PATRÓN puede contener variables, que serán interpoladas cada vez que el patrón de búsqueda sea evaluado, 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 ser interpolada. 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:

  1. 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).
  2. 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).

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, es usada en su lugar la última exitosa expresión regular coincidente. En este caso, sólo las opciones g y c en el patrón vacío son tomadas en cuenta; las otras opciones son tomadas 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 sobre esto, pero algunos casos patológicos podría ocurrir esa confusión, como en $a/// (¿esto es ($a) / (//) o $a // /?) y print $fh // (¿print $fh(// o print($fh //?). En todos estos ejemplos, Perl asumirá que significaba definido-o. Si usted quiere decir la expresión regular vacía, sólo tiene que utilizar paréntesis o espacios para eliminar la ambigüedad, o incluso el prefijar con una m (así que // se convierte en m//).

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 aquí $1, etc., también son establecidas, y que esto difiere del comportamiento de Perl 4). 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 fueron asignadas; es decir, si el patrón emparejó.

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ón pos(); 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 ejemplo m//gc). Modificando la cadena objetivo también restablece la posición de búsqueda.

Aserción \G

Puede entremezclar coincidencias m//g con m/\G.../g, donde \G es una aserción de ancho cero que coincide con la posición exacta en que la anterior m//g, si hubo, se detuvo. Sin el modificador /g, la aserción \G todavía se ancla en pos() como si fuera al principio de la operación (vea "pos" in perlfunc), pero la coincidencia, por supuesto, sólo es probada 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 soportado cuando es anclado 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-blanco
        (?<! \b [DMS]r  )           # pero no es una abreviatura conocida
        (?<! \b Mrs )
        (?<! \b Sra )
        (?<! \b St  )
        [.?!]                       # seguido por un terminador de sentencia
        (?= $ | \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 de p, 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. Si la última coincidencia, es, en su lugar, p, es una buena apuesta 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 regexp intenta coincidir donde la anterior lo dejó.

 $_ = <<'EOL';
    $url = URI::URL->new( "http://ejemplo.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(" Capitalizado"), 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?msixpodualgc
?PATRÓN?msixpodualgc

Esto es igual que la búsqueda m/patrón/, salvo que coincide una sola vez entre llamadas al operador reset(). 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 son reinicializados los patrones locales m?? 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, es controlada por el delimitador que comienza por ?; con cualquier otro delimitador, se trata del habitual operador m//.

Por razones históricas, la m precedente en m?PATRÓN? es opcional, pero la sintaxis resultante ?PATRÓN? es obsoleta, generando una advertencia sobre su uso y que puede ser eliminada de una próxima versión estable de Perl (¡sin previo aviso!).

s/PATRÓN/REEMPLAZO/msixpodualgcer

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 ivalor 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 será interpolada en el patrón, en tiempo de ejecución. Si desea que el patrón sea compilado solo la primera vez que la variable sea interpola, 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. Ver perlre para una explicación más detallada sobre esto.

Las opciones son como las de m// con la adición de las opciones de reemplazo específicas 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). A diferencia de Perl 4, Perl 5 trata las comillas simples invertidas como delimitadores normales; el texto de reemplazo no es evaluado como un comando. Si el PATRÓN está delimitado por paréntesis, corchetes, llaves, el REEMPLAZO tiene su propio par de delimitadores, que puede o no estar encerrado entre los mismos delimitadores; por ejemplo, s(foo)(bar) o s<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 modificador e hará que la parte de reemplazo sea evaluada 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/ese/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';
    $a = s/abc/def/r;           # $a 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 variables escalar incrustada
    # (incluyendo léxicas) en $_ : Primero $1 es interpolado
    # al nombre de la variable, y entonces, evaluada
    s/(\$\w+)/$1/eeg;

    # Eliminar (la mayoría) comentarios 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 solo se puede utilizar un /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;

s///le es tratada como una sustitución seguida por el operador le, no las opciones /le. Esto puede cambiar en una futura versión de Perl. Genera una advertencia si las advertencias están habilitadas. Para eliminar la ambigüedad, use un espacio o cambie el orden de las opciones:

    s/foo/bar/ le 5;  # "le" operador infijo
    s/foo/bar/el;     # opciones "e" y "l"

Operadores de entrecomillado

q/CADENA/
'CADENA'

Un entrecomillado simple, una cadena de caracteres literal. 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 es interpolada.

    $_ .= 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 luego 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>&-`;

Leer tanto el STDOUT como el STDERR de un comando, pero separadamente, es más fácil hacerlos redireccionar separadamente 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 fichero 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 esta cadena es evaluada, está sujeta 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 ellos sean tratados literalmente. Esto es 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() y exec() 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 shell cmd de Windows NT).

A partir de la versión v5.6.0, 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 (ver perlport). Para estar seguro, es posible que necesite el conjunto | ($AUTOFLUSH en English) o llame al método autoflush() de IO::Handle en cualquier identificador abierto.

Tenga en cuenta que algunos shell de comandos puede 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 necesaria interpolación. 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ían entre sistemas, y de hecho no pueden estar presentes en todos. Como ejemplo, el comando type en el shell POSIX es muy diferente del comando type 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 lo que te está metiendo.

Vea "Operadores E/S" para más discusiones.

qw/CADENA/

Evalúa a una lista de palabras extraídas de CADENA, utilizando los espacios en blanco incrustados 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 una coma o poner comentarios en una cadena qw multilínea. Por esta razón, el pragma use warnings y la opción -w (es decir, la variable $^W) produce advertencias de 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 !~, la cadena $_ es transliterada.

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 ivalor.

Un intervalo de caracteres se puede especificar con un guión, por lo que tr/A-J/0-9/ es la sustitución de tr/ACEGIBDFHJ/0246813579/. Para los devotos de sed, y se ofrece como un sinónimo de tr. 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] o tr(+\-*/)/ABCD/.

Tenga en cuenta que tr no usa expresiones regulares de clases de caracteres, tales como \d o \pL. El operador tr no es equivalente a la utilidad tr(1). Si desea mapear cadenas entre minúsculas/mayúsculas, vea "lc" in perlfunc y "uc" in perlfunc; y, en general, considere usar el operador s 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, pero tr[a-z][A-Z], no (excepto en algunos viejos sistemas de 7 bits).

Tenga en cuenta también que la idea de rango es poco transportable entre conjuntos de caracteres; e incluso dentro de los mismos conjuntos de caracteres pueden causar resultados que probablemente no espera. Un buen principio es el de usar rangos que sólo comiencen y terminen, en cualquier alfabeto, con un mismo tamaño de caja (a-e, A-E), o dígitos (0-4). Cualquier otro caso no es seguro. 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.
    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 sea encontrado 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 encuentre 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 es interpretada exactamente como esté especificada. De lo contrario, si la LISTA_REEMPLAZO es más corta que la LISTA_BÚSQUEDA, el carácter final es replicado hasta que sea lo suficientemente larga. Si la LISTA_REEMPLAZO está vacía, la LISTA_BÚSQUEDA es replicada. 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" (este-documento, documento incrustado). Siguiendo a << 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 indicado 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 que lo comenzó.
    FINIS

Si utiliza un documento incrustado en una construcción delimitada, como en s///eg, el material entrecomillado debe venir en las siguientes líneas al delimitador final. Así que en lugar de

    s/este/<<E . 'ese'
    el otro
    E
     . 'más '/eg;

tiene que escribir

    s/este/<<E . 'ese'
     . 'más '/eg;
    el otro
    E

Si el identificador de final está en la última línea del programa, debe asegurarse de que hay un carácter de nueva línea después de él; de lo contrario, Perl dará la advertencia Can't find string terminator "END" anywhere before EOF....

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 puede abarcar varias 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 maneja 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 encuentra al 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, donde la información sobre los delimitadores se utiliza en el análisis. Durante esta búsqueda, el texto entre los delimitadores inicial y final se copia a un lugar seguro. El texto copiado es independiente de los delimitadores.

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 un EOF 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.

Para las construcciones, salvo los documentos incrustados, caracteres simples son utilizados como delimitadores de inicio y finalización. 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ón qq//, mientras que un ] termina las construcciones qq[] y qq]].

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 entre emparejados, las parejas anidadas también se omiten. Por ejemplo, mientras se busca el ] de cierre emparejado con el de apertura [, combinaciones de \\, \] y \[ son todos omitidos, y anidados de [ y ] se pasan también por alto. Sin embargo, cuando se usan las barras diagonales inversas como delimitadores (como qq\\ y tr\\\), no se omite nada. Durante la búsqueda del final, las barras diagonales inversas que escapan delimitadores son eliminados (hablando más exactamente, no se copian al lugar seguro).

Para construcciones con delimitadores en tres partes (s///, y///, y tr///), 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, como s!!! y tr))), 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 en s(){} y tr[]//. En estos casos, los espacios en blanco y los comentarios están permitidos entre ambas partes, aunque 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 la barra diagonal que terminó m// fue seguida por un SPACE, el ejemplo anterior no es m//x, sino más bien m//, 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 \ en qq/\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 de s'''

No se realiza interpolación en esta etapa. Cualquier secuencia de barras diagonales inversas, incluyendo \\ son tratadas en la fase "analizando expresiones regulares".

'', q//, tr''', y''', y el reemplazo de s'''

La única interpolación es la eliminación de \ a partir de pares de \\. Por lo tanto, - en tr''' y y''' es tratado, literalmente, como un guion, y por lo tanto no está disponible un intervalo de caracteres. \1 en el reemplazo de s''' 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 - es tratado de forma especial y por lo tanto \- es tratado como un literal -.

"", ``, qq//, qx//, <file*glob>, <<"EOF"

\Q, \U, \u, \L, \l, \F (posiblemente emparejadas con \E) son convertidas a las correspondientes construcciones Perl. Así, "$foo\Qbaz$bar" es convertida internamente a $foo . (quotemeta("baz" . $bar)). Las otras secuencias de escape, como \200 y \t y caracteres escapados con barras diagonales inversas, como \\ y \-, son reemplazadas con expansiones apropiadas.

Hay que hacer hincapié en que lo que caiga dentro de \Q y \E es interpolado de la forma normal. Algo como "\Q\\E" no tiene dentro a \E. en cambio, tiene a \Q, \\, y E, 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" es convertido a quotemeta("\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 son convertidos 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 STRING \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 \, $ será escapado para convertirse en "\\\$"; si no, es interpretado 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, si "a $b -> {c}" realmente significa:

  "a " . $b . " -> {c}";

o:

  "a " . $b -> {c};

La mayoría de las veces, 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, por lo general es correcta 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 construcciones qq//.

Es en este paso que \1 es convertido, de mala gana, en $1 en el texto de reemplazo de s///, 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. Una advertencia es emitida si están activos el pragma use 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 construcciones qq//.

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 \ seguido de un carácter no va a ser sustituido, sino sólo obviado, con el fin de analizarlos como expresiones regulares en el paso siguiente. Como \c es omitido en este paso, @ de \c@ en RE es posiblemente tratado como un símbolo de array (por ejemplo @foo), incluso aunque el mismo texto en qq// sí da la interpolación de \c@.

Por otra parte, 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 caso en el que la presencia del modificador //x es relevante.

La interpolación en los patrones tiene varias peculiaridades: $|, $(, $), @+ y @- no son interpoladas, y 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]}/ es interpretada 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 en s*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 es mx, y después de la eliminación de los delimitadores, la RE es la misma que m/ ^ 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 ulteriormente.

analizando expresiones regulares

Pasos previos se realizaron durante la compilación de 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 si la concatenación, unión, traducción de tamaño de caja, o metaentrecomillado están involucrados, el string resultante es pasado 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 es ignorado (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 [ es tratado como si estuviera precedido por una barra diagonal inversa. Del mismo modo, el terminador de (?{...}) es encontrado usando las mismas reglas como para encontrar el terminador de una construcción delimitada por {}.

Es posible inspeccionar tanto la cadena dada al motor RE y el autómata finito que resulta. Ver los argumentos debug/debugcolor en el pragma use 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 está aquí descrito solo por 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 es interpretado 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 por un undef, posteriormente.

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 es automáticamente asignado 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 esta, 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 final de salto de línea. Si realmente quiere mirar por esos valores para terminar el bucle, deben hacerse la prueba de forma explícita:

    while (($_ = <STDIN>) ne '0') { ... }
    while (<STDIN>) { last unless $_; ... }

En otros contextos booleanos, <GESTOR_ARCHIVO> sin una explícita prueba 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). Identificadores de archivo adicionales pueden ser creados con la función open(), entre otros. Vea perlopentut y "open" in perlfunc para más detalles sobre esto.

Si un <IDENTIFICADOR_ARCHIVO> es utilizado en un contexto en el que está esperando una lista, es devuelta 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 puede ser escrito como readline(*IDENTIFICADOR_ARCHIVO). Vea "readline" in perlfunc.

El identificador de archivo nulo <> es especial: puede ser utilizado 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 <> es evaluado, el array @ARGV es comprobado, y si está vacío, $ARGV[0] es configurado a "-", que cuando sea abierto le ofrecerá a usted la entrada estándar. Luego, el array @ARGV es procesado 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 funciona de forma efectiva. 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 justo 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 *|', realmente abre una tubería, ejecuta el comando rm y lee la salida de rm desde esa tubería. Si desea que todos los elementos de @ARGV deban ser interpretados como nombres de archivo, puede utilizar el módulo ARGV::readonly de CPAN.

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. Esto establecerá @ARGV a todos los archivos de texto sin formato si no se indicó nada a @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 lo llama de nuevo, después, asumirá que está procesando otra lista @ARGV, y si no ha configurado @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 por comilla doble, 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 ser leídos 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 ser manipulados 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 bit 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

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.

Usado en números, los operadores binarios ("&", "|", "^", "~", "<<", y ">>") 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 efecto, 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á siendo utilizado por 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 bigint, bigrat y bigfloat, proporcionan aritmética con 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;
        $a = 3/22;
        $b = 4/6;
        say "a/b es ", $a/$b;
        say "a*b es ", $a*$b;
    a/b es 9/44
    a*b is 1/11

Hay varios módulos que permiten calcular con precisión fija o ilimitada (limitada únicamente por la memoria y el 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::Fraction                grandes e ilimitadas fracciones, como 9973 / 12967
  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::BigInteger              usa una biblioteca C externa
  Math::Cephes                  usa 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

Elija con cuidado.

Jump to Line
Something went wrong with that request. Please try again.