¿Características ocultas de Perl?

143

¿Cuáles son algunas de las características de lenguaje realmente útiles pero esotéricas en Perl que realmente has podido emplear para hacer un trabajo útil?

Pautas:

  • Intente limitar las respuestas al núcleo de Perl y no a CPAN
  • Por favor da un ejemplo y una breve descripción

Las características ocultas también se encuentran en las características ocultas de otros idiomas:

(Todo esto es de la respuesta de Corion )

  • C
    • Dispositivo de Duff
    • Portabilidad y Estandaridad
  • C#
    • Cotizaciones para listas y cadenas delimitadas por espacios en blanco
    • Espacios de nombres aliables
  • Java
    • Initalizadores Estáticos
  • JavaScript
    • Las funciones son ciudadanos de primera clase.
    • Bloqueo de alcance y cierre
    • Llamando métodos y accesos indirectamente a través de una variable
  • Rubí
    • Definiendo métodos a través del código
  • PHP
    • Documentación en línea generalizada
    • Métodos mágicos
    • Referencias simbólicas
  • Pitón
    • Intercambio de valor de una línea
    • Capacidad para reemplazar incluso las funciones principales con su propia funcionalidad

Otras características ocultas:

Operadores:

Citando construcciones:

Sintaxis y Nombres:

Módulos, pragmas y opciones de línea de comandos:

Variables:

Bucles y control de flujo:

Expresiones regulares:

Otras características:

Otros trucos y meta respuestas:


Ver también:

Adam Bellaire
fuente
La mayoría de estas características son de uso cotidiano, algunas ocurren en la mayoría de los scripts de Perl, y la mayoría de las que figuran en "Otros" aún provienen de otros idiomas, y llama a estos cambios "ocultos" la intención de la pregunta.
reinierpost

Respuestas:

54

El operador de flip-flop es útil para omitir la primera iteración al recorrer los registros (generalmente líneas) devueltos por un identificador de archivo, sin usar una variable de indicador:

while(<$fh>)
{
  next if 1..1; # skip first record
  ...
}

Ejecute perldoc perlopy busque "flip-flop" para obtener más información y ejemplos.

John Siracusa
fuente
En realidad, eso está tomado de Awk, donde puedes hacer flip-flop entre dos patrones escribiendo pattern1, pattern2
Bruno De Fraine
15
Para aclarar, el aspecto "oculto" de esto es que si cualquiera de los operandos al escalar '...' es una constante, el valor se compara implícitamente con el número de línea de entrada ($.)
Michael Carman
47

Hay muchas características no obvias en Perl.

Por ejemplo, ¿sabías que puede haber un espacio después de un sigilo?

 $ perl -wle 'my $x = 3; print $ x'
 3

¿O que puede dar nombres numéricos subs si usa referencias simbólicas?

$ perl -lwe '*4 = sub { print "yes" }; 4->()' 
yes

También está el cuasi operador "bool", que devuelve 1 para expresiones verdaderas y la cadena vacía para falsas:

$ perl -wle 'print !!4'
1
$ perl -wle 'print !!"0 but true"'
1
$ perl -wle 'print !!0'
(empty line)

Otras cosas interesantes: con use overloadusted puede sobrecargar los literales de cadena y los números (y, por ejemplo, hacerlos BigInts o lo que sea).

Muchas de estas cosas están realmente documentadas en alguna parte, o se siguen lógicamente de las características documentadas, pero no obstante, algunas no son muy conocidas.

Actualización : otra buena. A continuación se q{...}mencionaron las construcciones de comillas, pero ¿sabía que puede usar letras como delimitadores?

$ perl -Mstrict  -wle 'print q bJet another perl hacker.b'
Jet another perl hacker.

Del mismo modo, puede escribir expresiones regulares:

m xabcx
# same as m/abc/
moritz
fuente
2
"¿Sabías que puede haber un espacio después de un sigilo?" Estoy completamente asombrado. Guau.
Aristóteles Pagaltzis
1
¡Frio! !! $ undef_var no crea una advertencia.
Axeman
44
Creo que su ejemplo de uso de letras para delimitar cadenas debería ser " Simplemente otro hacker perl" en lugar de "Jet otro hacker perl" = P
Chris Lutz
La peor parte es que también puedes usar otras cosas como delimitadores. Incluso cerrando corchetes. Los siguientes son válidos: s} regex} reemplazo} xsmg; q] cadena literal];
Ryan C. Thompson
46

Agregue soporte para archivos comprimidos a través de magic ARGV :

s{ 
    ^            # make sure to get whole filename
    ( 
      [^'] +     # at least one non-quote
      \.         # extension dot
      (?:        # now either suffix
          gz
        | Z 
       )
    )
    \z           # through the end
}{gzcat '$1' |}xs for @ARGV;

(cita alrededor de $ _ necesario para manejar nombres de archivos con metacaracteres de shell)

Ahora la <>función descomprimirá cualquier @ARGVarchivo que termine con ".gz" o ".Z":

while (<>) {
    print;
}
timkay
fuente
2
No creo que necesites escapar |en el reemplazo.
Chris Lutz el
Estoy mirando esto y no puedo entender cómo funciona. ¿En qué punto se zcat |analiza como un comando para canalizar?
Ether
1
@Ether => la detección de tuberías es una característica de los dos argumentos abiertos, que el operador de diamantes utiliza cuando abre cada archivo@ARGV
Eric Strom,
40

Una de mis características favoritas en Perl es usar el ||operador booleano para seleccionar entre un conjunto de opciones.

 $x = $a || $b;

 # $x = $a, if $a is true.
 # $x = $b, otherwise

Esto significa que uno puede escribir:

 $x = $a || $b || $c || 0;

para dar el primer valor verdadero de $a, $by $c, o un incumplimiento de 0lo contrario.

En Perl 5.10, también está el //operador, que devuelve el lado izquierdo si está definido, y el lado derecho de lo contrario. Los siguientes selecciona la primera definido valor de $a, $b, $c, o 0de otro modo:

$ x = $ a // $ b // $ c // 0;

Estos también se pueden usar con sus formas abreviadas, que son muy útiles para proporcionar valores predeterminados:

$ x || = 0; # Si $ x era falso, ahora tiene un valor de 0.

$ x // = 0; # Si $ x no estaba definido, ahora tiene un valor de cero.

Cheerio

Pablo

pjf
fuente
44
Este es un idioma tan común que difícilmente califica como una característica "oculta".
Michael Carman
3
lástima que la bonita impresora piense // es un comentario :)
John Ferguson
2
Pregunta, ¿hay una "función de uso" para usar estos nuevos operadores, o están habilitados por defecto? Todavía estoy inclinando las características de Perl 5.10.
JJ
66
// está allí por defecto, no se necesitan ajustes especiales. También puede hacer una copia de seguridad en 5.8.x con el parche dor ... consulte el directorio autores / id / H / HM / HMBRAND / en cualquier espejo CPAN. FreeBSD 6.xy más allá hace esto por usted en su paquete perl.
Dland
2
Cuando || o // se combina con do {}, puede encapsular una asignación más compleja, es decir, $ x = $ a || do {my $ z; 3 o 4 líneas de derivación; $ z};
RET
39

Los operadores ++ y unario: no solo funcionan en números, sino también en cadenas.

my $_ = "a"
print -$_

impresiones -a

print ++$_

impresiones b

$_ = 'z'
print ++$_

imprime aa

Leon Timmermans
fuente
3
Para citar perlvar: "El operador de decremento automático no es mágico". Entonces --no funciona con cuerdas.
Moritz
"aa" no parece ser el elemento natural que sigue a "z". Esperaría el siguiente valor ascii más alto, que es "{".
Ether
44
No le pregunte a un programador qué viene después de "z"; Pregúntale a un humano. Esta característica es excelente para numerar elementos en una lista larga.
Barry Brown
17
Cuando era nuevo en Perl, implementé esta función con el comportamiento exacto de z a a y luego se la mostré a un compañero de trabajo que se rió y a mí y me dijo "déjame mostrarte algo". Lloré un poco pero aprendí algo.
Copas
2
@Ether: si lo desea, use números y conviértalos automáticamente a ASCII ord(). O escriba una clase pequeña y sobrecargue a los operadores para que lo hagan por usted.
Chris Lutz
36

Como Perl tiene casi todas las partes "esotéricas" de las otras listas, le diré una cosa que Perl no puede:

Lo único que Perl no puede hacer es tener URL arbitrarias desnudas en su código, porque el //operador se usa para expresiones regulares.

En caso de que no fuera obvio para usted qué características ofrece Perl, aquí hay una lista selectiva de las entradas quizás no totalmente obvias:

Dispositivo de Duff - en Perl

Portabilidad y estandarización : es probable que haya más computadoras con Perl que con un compilador de C

Una clase de manipulación de archivos / rutas : File :: Find funciona incluso en más sistemas operativos que .Net

Cotizaciones para listas y cadenas delimitadas por espacios en blanco : Perl le permite elegir citas casi arbitrarias para su lista y delimitadores de cadena

Espacios de nombres aliables : Perl los tiene mediante asignaciones globales:

*My::Namespace:: = \%Your::Namespace

Inicializadores estáticos : Perl puede ejecutar código en casi todas las fases de compilación y creación de instancias de objetos, desde BEGIN(análisis de código) a CHECK(después del análisis de código) a import(en la importación del módulo) a new(creación de objetos) a DESTROY(destrucción de objetos) a END(salida del programa)

Las funciones son ciudadanos de primera clase , como en Perl

Bloqueo de alcance y cierre : Perl tiene ambas

Llamando métodos y accesores indirectamente a través de una variable : Perl también lo hace:

my $method = 'foo';
my $obj = My::Class->new();
$obj->$method( 'baz' ); # calls $obj->foo( 'baz' )

Definición de métodos a través del código : Perl también lo permite :

*foo = sub { print "Hello world" };

Documentación en línea omnipresente - documentación de Perl está en línea y probablemente en su sistema demasiado

Métodos mágicos que se llaman cada vez que se llama una función "no existente": Perl implementa eso en la función AUTOLOAD

Referencias simbólicas : se recomienda mantenerse alejado de ellas. Se comerán a tus hijos. Pero, por supuesto, Perl le permite ofrecer a sus hijos demonios sedientos de sangre.

Intercambio de valores de una línea : Perl permite la asignación de listas

Capacidad para reemplazar incluso las funciones principales con su propia funcionalidad

use subs 'unlink'; 
sub unlink { print 'No.' }

o

BEGIN{
    *CORE::GLOBAL::unlink = sub {print 'no'}
};

unlink($_) for @ARGV
Corion
fuente
Soy fanático de la documentación de Perl en comparación con otros lenguajes, pero sigo pensando que para Regexes y referencias podría racionalizarse mucho. Por ejemplo, la mejor cartilla para expresiones regulares no es Perlre, sino Perlop
John Ferguson
9
"Lo único que Perl no puede hacer es tener URL arbitrarias desnudas en su código, porque el operador // se usa para expresiones regulares". Esto no tiene sentido.
Gracias por su comprensión. He visto algunas formas de tener una http: // ... URL desnuda en el código Perl sin usar un filtro de origen, y no encontré una manera. ¿Quizás pueda mostrar cómo esto es posible? // se usa para expresiones regulares en versiones de Perl hasta 5.8.x. En 5.10 se reutiliza para definir o asignar.
Corion
8
¿Por qué / dónde querrías URL desnudas en tu código? No puedo pensar en un ejemplo.
náufrago
18
Nadie querría eso, es solo un meme de Java. " foo.com " es la etiqueta http: y luego "foo.com" en un comentario. Algunas personas encuentran esto interesante porque ... son tontas.
jrockway
35

Autovivification . AFAIK no tiene otro idioma .

JJ
fuente
No tenía idea de que Python, et al, no apoyaban esto.
skiphoppy
@davidnicol: ¿En serio? ¿Puedes proporcionar un enlace? Mi búsqueda rápida en google no devolvió nada. Para aquellos que no conocen ECMAscript es el nombre correcto para Javascript. en.wikipedia.org/wiki/ECMAScript
JJ
1
Y hay un módulo para deshabilitar la autoviviencia
Alexandr Ciornii
1
@Gregg Lind: dado que Python crea automáticamente variables cada vez que las asigna por primera vez, la autovivificación crearía problemas monstruosos de un solo error tipográfico.
Chris Lutz
3
@tchrist - a = [[x * y para y en xrange (1,11)] para x en xrange (1,11)]
Omnifarious
31

Es simple citar casi cualquier tipo de cadena extraña en Perl.

my $url = q{http://my.url.com/any/arbitrary/path/in/the/url.html};

De hecho, los diversos mecanismos de cotización en Perl son bastante interesantes. Los mecanismos de comillas tipo Regex de Perl le permiten citar cualquier cosa, especificando los delimitadores. Puede usar casi cualquier carácter especial como #, / o caracteres de apertura / cierre como (), [] o {}. Ejemplos:

my $var  = q#some string where the pound is the final escape.#;
my $var2 = q{A more pleasant way of escaping.};
my $var3 = q(Others prefer parens as the quote mechanism.);

Mecanismos de cotización:

q: cita literal; El único personaje que necesita escapar es el personaje final. qq: una cita interpretada; procesa variables y caracteres de escape. Ideal para cadenas que necesita citar:

my $var4 = qq{This "$mechanism" is broken.  Please inform "$user" at "$email" about it.};

qx: funciona como qq, pero luego lo ejecuta como un comando del sistema, no de forma interactiva. Devuelve todo el texto generado a partir de la salida estándar. (La redirección, si es compatible con el sistema operativo, también sale) También se hace con comillas inversas (el carácter `).

my $output  = qx{type "$path"};      # get just the output
my $moreout = qx{type "$path" 2>&1}; # get stuff on stderr too

qr: Interpreta como qq, pero luego lo compila como una expresión regular. Funciona con las diversas opciones en la expresión regular también. Ahora puede pasar la expresión regular como una variable:

sub MyRegexCheck {
    my ($string, $regex) = @_;
    if ($string)
    {
       return ($string =~ $regex);
    }
    return; # returns 'null' or 'empty' in every context
}

my $regex = qr{http://[\w]\.com/([\w]+/)+};
@results = MyRegexCheck(q{http://myurl.com/subpath1/subpath2/}, $regex);

qw: un operador de cotizaciones muy, muy útil. Convierte un conjunto de palabras separadas por espacios en blanco en una lista. Excelente para completar datos en una prueba unitaria.


   my @allowed = qw(A B C D E F G H I J K L M N O P Q R S T U V W X Y Z { });
   my @badwords = qw(WORD1 word2 word3 word4);
   my @numbers = qw(one two three four 5 six seven); # works with numbers too
   my @list = ('string with space', qw(eight nine), "a $var"); # works in other lists
   my $arrayref = [ qw(and it works in arrays too) ]; 

Son geniales para usarlos cada vez que aclara las cosas. Para qx, qq y q, lo más probable es que use los operadores {}. El hábito más común de las personas que usan qw suele ser el operador (), pero a veces también se ve qw //.

Robert P
fuente
1
A veces uso qw "" para que los resaltadores de sintaxis lo resalten correctamente.
Brad Gilbert
Funciona para mí en SlickEdit. :)
Robert P
1
@fengshaun, Los editores que utilizan generalmente hacer resaltar estos correctamente. Me refería, en parte, al resaltador de sintaxis en StackOverflow.
Brad Gilbert
@Brad Gilbert: Stack Overflow no puede (bueno, (no) analiza Perl vale la pena en cuclillas.
my $moreout = qx{type "$path" 2>&1};... ¡No sabía que podías hacer eso! [TM]
dland
27

No está realmente oculto, pero muchos programadores de Perl no saben todos los días acerca de CPAN . Esto se aplica especialmente a las personas que no son programadores a tiempo completo o que no programan en Perl a tiempo completo.

mpeters
fuente
27

La declaración "for" se puede usar de la misma manera que "with" se usa en Pascal:

for ($item)
{
    s/&‎nbsp;/ /g;
    s/<.*?>/ /g;
    $_ = join(" ", split(" ", $_));
}

Puede aplicar una secuencia de s /// operaciones, etc. a la misma variable sin tener que repetir el nombre de la variable.

NOTA: el espacio que no se rompe arriba (& nbsp;) ha ocultado Unicode para evitar el Markdown. No copie y pegue :)

timkay
fuente
Y "map" también hace el mismo truco ... map {....} $ item; Una ventaja de usar "para" sobre "mapa" sería que podría usar el siguiente para salir.
draegtun
2
Además, for tiene el elemento que se está manipulando antes del código que realiza la manipulación, lo que mejora la legibilidad.
Robert P
@RobertP: Eso es correcto. Un topicalizador es útil en el discurso.
tchrist
26

El operador quoteword es una de mis cosas favoritas. Comparar:

my @list = ('abc', 'def', 'ghi', 'jkl');

y

my @list = qw(abc def ghi jkl);

Mucho menos ruido, más fácil para la vista. Otra cosa realmente buena de Perl, que uno realmente echa de menos cuando escribe SQL, es que una coma final es legal:

print 1, 2, 3, ;

Eso parece extraño, pero no si sangra el código de otra manera:

print
    results_of_foo(),
    results_of_xyzzy(),
    results_of_quux(),
    ;

Agregar un argumento adicional a la llamada a la función no requiere que juegues con comas en líneas anteriores o finales. El cambio de una sola línea no tiene impacto en sus líneas circundantes.

Esto hace que sea muy agradable trabajar con funciones variadas. Esta es quizás una de las características más subestimadas de Perl.

soso
fuente
2
Un caso interesante de la sintaxis de Perl es que lo siguiente es válido: por $ _ qw (una lista de cosas) {...}
ephemiente
1
Incluso puede abusar de la sintaxis global para citar palabras, siempre que no utilice caracteres especiales como * Para que pueda escribirfor (<a list of stuff>) { ... }
moritz
1
@ephemient: casi. Eso solo funciona con léxicos: para mi $ x qw (abc) {...} Por ejemplo: para $ _ qw (abc) {print} # no imprime nada
dland
¿Por qué agregar ese léxico adicional cuando puedes disfrutar del valor predeterminado favorito de Perl? para (qw / abcd /) {print; }
fengshaun
2
@ephemient, @fengshaun, @moritz, @dland: Eso está "arreglado" en la nada ; ver este hilo p5p .
tchrist
26

La capacidad de analizar datos directamente pegados en un bloque DATA . No es necesario guardar en un archivo de prueba para abrirlo en el programa o similar. Por ejemplo:

my @lines = <DATA>;
for (@lines) {
    print if /bad/;
}

__DATA__
some good data
some bad data
more good data 
more good data 
allan
fuente
¡Y muy útil en pequeñas pruebas!
fengshaun
@peter mortensen ¿cómo tendrías múltiples bloques? ¿Y cómo terminas un bloque?
Sapo
@Toad: es la respuesta de allan (ver la lista de revisión). Es mejor dirigirse a ese usuario. O, como ese usuario ha dejado Stack Overflow, tal vez no se dirija a nadie en particular (para que un verdadero experto en Perl pueda solucionarlo más adelante).
Peter Mortensen el
3
@Hai: No es que no fea - de hecho, es precisamente lo contrario de fea: es limpio, esbelta, mínimo, y hermoso; en una palabra, es maravilloso, y los idiomas sin él son un PITA. @peter mortensen, @toad: Una respuesta a cómo tener múltiples bloques de datos en el mismo programa es usar el módulo Inline :: Files de CPAN.
tchrist
Inline :: Files se implementa utilizando filtros de origen. También hay Data :: Section que proporciona múltiples bloques en línea y no utiliza filtros de origen.
Prakash K
24

Nuevas operaciones de bloque

Yo diría que la capacidad de expandir el lenguaje, crear operaciones de pseudobloque es una.

  1. Declaras el prototipo de un sub que indica que primero toma una referencia de código:

    sub do_stuff_with_a_hash (&\%) {
        my ( $block_of_code, $hash_ref ) = @_;
        while ( my ( $k, $v ) = each %$hash_ref ) { 
            $block_of_code->( $k, $v );
        }
    }
  2. Entonces puedes llamarlo así en el cuerpo

    use Data::Dumper;
    
    do_stuff_with_a_hash {
        local $Data::Dumper::Terse = 1;
        my ( $k, $v ) = @_;
        say qq(Hey, the key   is "$k"!);
        say sprintf qq(Hey, the value is "%v"!), Dumper( $v );
    
    } %stuff_for
    ;

( Data::Dumper::Dumperes otra gema semi-oculta). Observe cómo no necesita la subpalabra clave frente al bloque o la coma antes del hash. Termina pareciéndose mucho a:map { } @list

Filtros de origen

Además, hay filtros de origen. Donde Perl te pasará el código para que puedas manipularlo. Tanto esto como las operaciones de bloque son prácticamente cosas que no se intentan en casa.

He hecho algunas cosas interesantes con filtros de origen, por ejemplo, crear un lenguaje muy simple para verificar el tiempo, permitiendo breves frases de Perl para tomar decisiones:

perl -MLib::DB -MLib::TL -e 'run_expensive_database_delete() if $hour_of_day < AM_7';

Lib::TL simplemente buscaría las "variables" y las constantes, las crearía y las sustituiría según fuera necesario.

Una vez más, los filtros de origen pueden ser desordenados, pero son potentes. Pero pueden confundir a los depuradores con algo terrible, e incluso las advertencias se pueden imprimir con los números de línea incorrectos. Dejé de usar Damian's Switch porque el depurador perdería toda capacidad de decirme dónde estaba realmente. Pero descubrí que puede minimizar el daño modificando pequeñas secciones de código, manteniéndolos en la misma línea.

Ganchos de señal

A menudo se hace lo suficiente, pero no es tan obvio. Aquí hay un manipulador de dados que se apoya en el viejo.

my $old_die_handler = $SIG{__DIE__};
$SIG{__DIE__}       
    = sub { say q(Hey! I'm DYIN' over here!); goto &$old_die_handler; }
    ;

Eso significa que siempre que algún otro módulo en el código quiera morir, tienen que acudir a usted (a menos que alguien más realice una sobrescritura destructiva $SIG{__DIE__}). Y se le puede notificar que alguien piensa que algo es un error.

Por supuesto, para suficientes cosas puedes usar un END { }bloque, si todo lo que quieres hacer es limpiar.

overload::constant

Puede inspeccionar literales de cierto tipo en paquetes que incluyen su módulo. Por ejemplo, si usa esto en su importsub:

overload::constant 
    integer => sub { 
        my $lit = shift;
        return $lit > 2_000_000_000 ? Math::BigInt->new( $lit ) : $lit 
    };

significará que cada entero mayor de 2 mil millones en los paquetes de llamadas se cambiará a un Math::BigIntobjeto. (Ver sobrecarga :: constante ).

Literales enteros agrupados

Mientras estamos en eso. Perl le permite dividir grandes números en grupos de tres dígitos y aún así obtener un número entero analizable. Nota 2_000_000_000arriba por 2 mil millones.

Axeman
fuente
55
Al usar los manejadores $ SIG { DIE }, se recomienda encarecidamente que inspeccione $ ^ S para ver si su programa realmente está muriendo, o simplemente está lanzando una excepción que se detectará. Por lo general, no quieres interferir con esto último.
pjf
¡El nuevo bloque es muy instructivo! Estaba pensando que era un lenguaje semántico! muchas gracias.
ZeroCool
Un uso instructivo del filtro de origen es NiceSlice de pdl ( pdl.perl.org/?docs=NiceSlice&title=PDL::NiceSlice ) para que no sea necesario usar el ->slicemétodo como método cada vez que se necesita un corte.
Joel Berger
24

La "x" binaria es el operador de repetición :

print '-' x 80;     # print row of dashes

También funciona con listas:

print for (1, 4, 9) x 3; # print 149149149
Bruno De Fraine
fuente
Esta es una razón por la cual Perl ha sido tan popular entre los hackers. perl -e 'imprimir 0x000 x 25';
JJ
44
Mi uso favorito para esto es generar marcadores de posición para la última parte de una instrucción SQL INSERT: @p = ('?') X $ n; $ p = unirse (",", @p); $ sql = "INSERTAR ... VALORES ($ p)";
skiphoppy
24

Comprobación de contaminación. Con la comprobación de contaminación habilitada, Perl morirá (o advertirá, con-t ) si intenta pasar datos contaminados (en términos generales, datos desde fuera del programa) a una función insegura (abrir un archivo, ejecutar un comando externo, etc.). Es muy útil al escribir scripts de setuid o CGI o cualquier cosa en la que el script tenga mayores privilegios que la persona que lo alimenta.

Goto mágico goto &subhace una cola optimizada.

El depurador.

use stricty use warnings. Estos pueden salvarte de un montón de errores tipográficos.

Glomek
fuente
1
¿Por qué otros idiomas no tienen esta característica? Esta característica utilizada hace que los scripts web de Perl sean un orden de magnitud más seguros.
Matthew Lock
22

Según la forma en que se implementan los interruptores "-n"y "-p"en Perl 5, puede escribir un programa aparentemente incorrecto que incluya }{:

ls |perl -lne 'print $_; }{ print "$. Files"'

que se convierte internamente a este código:

LINE: while (defined($_ = <ARGV>)) {
    print $_; }{ print "$. Files";
}
Sec
fuente
@martin clayton: ¿Por qué se llama así?
tchrist
@tchrist - porque, supuestamente, parece que dos personas se frotan la nariz. De perfil, si ves lo que quiero decir.
Martin
18

Comencemos fácil con el operador de la nave espacial .

$a = 5 <=> 7;  # $a is set to -1
$a = 7 <=> 5;  # $a is set to 1
$a = 6 <=> 6;  # $a is set to 0
Segundo
fuente
1
@Leon: C / C ++ no hace un retorno de 3 valores para los números. Si la memoria sirve, las funciones de cadena de comapre son el único retorno de 3 valores que conozco en todo el lenguaje STL. AFAIK Python no tiene una comparación numérica de 3 retornos. Java tampoco tiene un número específico de comparación de retorno 3.
JJ
77
Vale la pena mencionar lo que es tan útil sobre los operadores de comparación -1/0/1, ya que no todos pueden saberlo: puede encadenarlos con el operador o para hacer primaria / secundaria / etc. ordena. Por lo tanto, ($a->lname cmp $b->lname) || ($a->fname cmp $b->fname)clasifica a las personas por sus apellidos, pero si dos personas tienen el mismo apellido, se ordenarán por su nombre.
hobbs
@JJ Python tiene una comparación de 3 valores: cmp () >>> print (cmp (5,7), cmp (6,6), cmp (7,5)) (-1, 0, 1)
bukzor
18

Esta es una meta respuesta, pero los archivos de Consejos de Perl contienen todo tipo de trucos interesantes que se pueden hacer con Perl. El archivo de consejos anteriores está en línea para navegar, y se puede suscribir a través de una lista de correo o un feed de átomos.

Algunos de mis consejos favoritos incluyen la construcción de ejecutables con PAR , el uso de autodie para lanzar excepciones automáticamente y el uso del interruptor y las construcciones de coincidencia inteligente en Perl 5.10.

Divulgación: Soy uno de los autores y mantenedores de Perl Tips, por lo que obviamente los considero muy bien. ;)

pjf
fuente
2
Es probablemente uno de los mejores lenguajes documentados, y establece el patrón de herramientas para buscar documentación. Que la lista en esta pregunta probablemente no sea tan necesaria como para otros idiomas.
Axeman
1
autodie se ve muy bien.
j_random_hacker
18

map - no solo porque hace que el código sea más expresivo, sino porque me dio el impulso de leer un poco más sobre esta "programación funcional".

brunorc
fuente
15

La cláusula continue en bucles. Se ejecutará en la parte inferior de cada bucle, incluso en los siguientes.

while( <> ){
  print "top of loop\n";
  chomp;

  next if /next/i;
  last if /last/i;

  print "bottom of loop\n";
}continue{
  print "continue\n";
}
Shawn H Corey
fuente
15

Mi voto sería para los grupos (? {}) Y (?? {}) en las expresiones regulares de Perl. El primero ejecuta el código Perl, ignorando el valor de retorno, el segundo ejecuta el código, utilizando el valor de retorno como una expresión regular.

Leon Timmermans
fuente
Perl inventó tantas extensiones regexp que otros programas ahora a menudo usan pcre (expresiones regulares compatibles con perl) en lugar del lenguaje regex original.
Sec.
Lea la pequeña propaganda aquí perldoc.perl.org/… :-D
JJ
Perl realmente ha (hasta donde yo sé), liderar la manada, cuando se trata de expresiones regulares.
Brad Gilbert
Esto, hasta donde yo sé, todavía es experimental, y puede que no funcione de la misma manera en futuros Perls. No quiere decir que no sea útil, pero se puede encontrar una versión ligeramente más segura e igual de útil en el indicador s /// command's / e: s/(pattern)/reverse($1);/ge;# invierte todo patterns.
Chris Lutz
@Chris Lutz, @Leon Timmerman: Tenga en cuenta que esas dos construcciones ahora son remanentes. También tenga en cuenta que el segundo ya no necesita ser utilizado para efectuar patrones recursivos, ahora que podemos recurrir en grupos de captura. @Brad Gilbert: Así es, aunque PCRE hace un buen trabajo al rastrearnos; Un área de excelencia de expresiones regulares donde Perl es completamente indiscutible es su acceso a las propiedades Unicode; vea mi distribución unitrio de uninames, unicharsy especialmente unipropspara ver solo una parte de lo que quiero decir.
tchrist
13
while(/\G(\b\w*\b)/g) {
     print "$1\n";
}

El ancla \ G. Es caliente .

JJ
fuente
3
... e indica la posición del final del partido anterior.
Dave Sherohman el
1
Pero tienes que llamar a tu expresión regular en contexto escalar.
davidnicol
@davidnicol: el código anterior funciona. ¿Puedes aclarar a qué te refieres?
JJ
13

El m//operador tiene algunos casos especiales oscuros:

  • Si lo usa ?como delimitador, solo coincide una vez, a menos que llame reset.
  • Si lo usa 'como delimitador, el patrón no se interpola.
  • Si el patrón está vacío, usa el patrón de la última coincidencia exitosa.
Michael Carman
fuente
2
¡Estos son más como trucos ocultos que características ocultas! No conozco a nadie a quien le gusten. Un hilo en p5p hace algún tiempo discutió la utilidad de una supuesta bandera m / $ foo / r, donde / r significaría que no hay interpolación (la letra no es importante) ya que nadie puede recordar lo de las comillas simples.
Dland
2
@dland: De acuerdo; Yo diría que estos ocultos mis características y nunca usaría en el código de producción.
Michael Carman
77
No puedo imaginar que un programador de Perl no pueda recordar (o incluso adivinar) que las comillas simples no significan interpolación. Su uso con esta semántica es casi universal en el lenguaje que preferiría que sea ​​así ...
sundar - Reinstate Monica el
y si el patrón está vacío y la última coincidencia exitosa se compiló con el modificador / o, a partir de entonces se quedará atascado en ese patrón.
davidnicol
1
Creo que el comportamiento del patrón vacío ha quedado en desuso. Principalmente porque un patrón como m / $ foo / se convierte en un error desagradable cuando $ foo está vacío.
Matthew S
12

El operador de null filehandle diamond<> tiene su lugar en la construcción de herramientas de línea de comandos. Actúa como si se <FH>leyera desde un identificador, excepto que selecciona mágicamente lo que se encuentre primero: nombres de archivo de línea de comando o STDIN. Tomado de perlop:

while (<>) {
...         # code for each line
}
Spoulson
fuente
44
También sigue la semántica de UNIX de usar "-" para significar "leer de stdin. Para que puedas hacerlo perl myscript.pl file1.txt - file2.txt, y Perl procesará el primer archivo, luego stdin, luego el segundo archivo.
Ryan C. Thompson
Puede hacer que overloadel <>operador en sus propios objetos ( <$var>) trabaje como un iterador. Sin embargo, no funciona como cabría esperar en el contexto de la lista.
dolmen
11

Bloques de código especiales comoBEGIN , CHECKy END. Vienen de Awk, pero funcionan de manera diferente en Perl, porque no está basado en registros.

El BEGINbloque se puede usar para especificar algún código para la fase de análisis; también se ejecuta cuando realiza la verificación de sintaxis y variable perl -c. Por ejemplo, para cargar variables de configuración:

BEGIN {
    eval {
        require 'config.local.pl';
    };
    if ($@) {
        require 'config.default.pl';
    }
}
revs Bruno De Fraine
fuente
11
rename("$_.part", $_) for "data.txt";

renombra data.txt.part a data.txt sin tener que repetirme.

timkay
fuente
10

Un poco oscuro es el "operador" tilde-tilde que fuerza el contexto escalar.

print ~~ localtime;

es lo mismo que

print scalar localtime;

y diferente de

print localtime;
Segundo
fuente
55
Esto es especialmente oscuro porque perl5.10.0 también presenta el "operador de coincidencia inteligente" ~~, que puede hacer coincidencias de expresiones regulares, puede ver si un elemento está contenido en una matriz, etc.
Moritz
Eso no es oscuro, está ofuscado (y es útil para golf y JAPH).
Michael Carman
¡Esto no es correcto! ~~ no es seguro en las referencias! Los enrosca.
Leon Timmermans
Bueno, sí. La secuenciación es lo que sucede con las referencias cuando se las obliga al contexto escalar. ¿Cómo hace que "~~ fuerce el contexto escalar" incorrecto?
Dave Sherohman
3
@Nomad Dervish: contexto escalar / = stringificación. por ejemplo, "$ n = @a" es un contexto escalar. "$ s = qq '@ a'" es stringificación. Con respecto a las referencias, "$ ref1 = $ ref2" es un contexto escalar, pero no se stringifica.
Michael Carman
9

empate, la interfaz de vinculación variable.

davidnicol
fuente
Tie :: File me salvó el día una vez!
mhd 03 de
9

El "modo de desesperación" de las construcciones de control de bucle de Perl que hace que busquen en la pila para encontrar una etiqueta coincidente permite algunos comportamientos curiosos que Test :: More aprovecha, para bien o para mal.

SKIP: {
    skip() if $something;

    print "Never printed";
}

sub skip {
    no warnings "exiting";
    last SKIP;
}

Ahí está el poco conocido archivo .pmc. "use Foo" buscará Foo.pmc en @INC antes de Foo.pm. Esto tenía la intención de permitir que el bytecode compilado se cargara primero, pero Module :: Compile aprovecha esto para almacenar en caché los módulos filtrados de origen para tiempos de carga más rápidos y una depuración más fácil.

La capacidad de convertir las advertencias en errores.

local $SIG{__WARN__} = sub { die @_ };
$num = "two";
$sum = 1 + $num;
print "Never reached";

Eso es lo que puedo pensar en la parte superior de mi cabeza que no se ha mencionado.

Schwern
fuente
9

El operador de cabra *:

$_ = "foo bar";
my $count =()= /[aeiou]/g; #3

o

sub foo {
    return @_;
}

$count =()= foo(qw/a b c d/); #4

Funciona porque la asignación de listas en contexto escalar produce el número de elementos en la lista que se asigna.

* Tenga en cuenta que no es realmente un operador

Chas Owens
fuente
Ese es el "operador" más (bueno, menos) hermoso jamás visto.
Chris Lutz el