Caratteristiche nascoste di Perl?


143

Quali sono alcune funzioni del linguaggio davvero utili ma esoteriche in Perl che sei stato effettivamente in grado di impiegare per fare un lavoro utile?

Linee guida:

  • Cerca di limitare le risposte al core Perl e non a CPAN
  • Fornisci un esempio e una breve descrizione

Funzionalità nascoste si trovano anche nelle funzionalità nascoste di altre lingue:

(Questi sono tutti dalla risposta di Corion )

  • C
    • Dispositivo di Duff
    • Portabilità e standardità
  • C #
    • Preventivi per liste e stringhe delimitate da spazi bianchi
    • Spazi dei nomi aliasable
  • Giava
    • Inattivizzatori statici
  • JavaScript
    • Le funzioni sono cittadini di prima classe
    • Portata e chiusura del blocco
    • Chiamare metodi e accessori indirettamente tramite una variabile
  • Rubino
    • Definizione dei metodi tramite codice
  • PHP
    • Pervasiva documentazione online
    • Metodi magici
    • Riferimenti simbolici
  • Pitone
    • Scambio di un valore di riga
    • Possibilità di sostituire anche le funzioni principali con le proprie funzionalità

Altre caratteristiche nascoste:

operatori:

Citazione costrutti:

Sintassi e nomi:

Moduli, pragmi e opzioni della riga di comando:

variabili:

Loop e controllo del flusso:

Espressioni regolari:

Altre caratteristiche:

Altri trucchi e meta-risposte:


Guarda anche:


La maggior parte di queste funzionalità sono di uso quotidiano, alcune si verificano nella maggior parte degli script Perl e la maggior parte elencata in "Altro" deriva ancora da altre lingue, chiamando queste "nascoste" cambia l'intento della domanda.
reinierpost,

Risposte:


54

L'operatore flip-flop è utile per saltare la prima iterazione durante il ciclo tra i record (di solito le righe) restituiti da un handle di file, senza usare una variabile flag:

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

Esegui perldoc perlope cerca "flip-flop" per ulteriori informazioni ed esempi.


In realtà è preso da Awk, dove puoi fare il flip-flop tra due pattern scrivendo pattern1, pattern2
Bruno De Fraine,

15
Per chiarire, l'aspetto "nascosto" di questo è che se uno degli operandi a ".." scalare è una costante, il valore viene implicitamente confrontato con il numero della riga di input ($.)
Michael Carman,

47

Ci sono molte caratteristiche non ovvie in Perl.

Ad esempio, sapevi che può esserci uno spazio dopo un sigillo?

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

O che puoi dare nomi numerici ai sottotitoli se usi riferimenti simbolici?

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

C'è anche l'operatore quasi "bool", che restituisce 1 per le espressioni vere e la stringa vuota per false:

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

Altre cose interessanti: con use overloadte puoi sovraccaricare letterali e numeri di stringa (e ad esempio renderli BigInts o altro).

Molte di queste cose sono in realtà documentate da qualche parte, o seguono logicamente dalle funzionalità documentate, ma alcune non sono molto conosciute.

Aggiornamento : un altro bello. Di seguito q{...}sono stati menzionati i costrutti di citazione, ma sapevi che puoi usare le lettere come delimitatori?

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

Allo stesso modo puoi scrivere espressioni regolari:

m xabcx
# same as m/abc/

2
"Sapevi che può esserci uno spazio dopo un sigillo?" Sono assolutamente sbalordito. Wow.
Aristotele Pagaltzis,

1
Freddo! !! $ undef_var non crea un avviso.
Axeman,

4
Penso che il tuo esempio di utilizzo delle lettere per delimitare le stringhe dovrebbe essere " Solo un altro hacker perl" anziché "Jet un altro hacker perl" = P
Chris Lutz,

La parte peggiore è che puoi usare anche altre cose come delimitatori. Persino le parentesi quadre. Sono validi: s} regex} sostituzione} xsmg; q] stringa letterale];
Ryan C. Thompson,

46

Aggiungi il supporto per i file compressi tramite 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;

(virgolette intorno a $ _ necessarie per gestire i nomi di file con metacaratteri della shell in)

Ora la <>funzione decomprimerà tutti i @ARGVfile che terminano con ".gz" o ".Z":

while (<>) {
    print;
}

2
Non penso che tu debba sfuggire |alla sostituzione.
Chris Lutz,

Lo sto fissando e non riesco a capire come funzioni. A che punto viene zcat |analizzato come comando da eseguire?
Ether

1
@Ether => il rilevamento di pipe è una caratteristica dei due argomenti open, che l'operatore diamond utilizza quando apre ogni file in@ARGV
Eric Strom

40

Una delle mie funzioni preferite in Perl sta usando l' ||operatore booleano per selezionare tra una serie di scelte.

 $x = $a || $b;

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

Questo significa che si può scrivere:

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

a prendere il primo valore vero dal $a, $be $c, o di un default di 0altrimenti.

In Perl 5.10, c'è anche l' //operatore, che restituisce il lato sinistro se definito, e il lato destro altrimenti. I seguenti seleziona la prima definito valore $a, $b, $c, o 0altrimenti:

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

Questi possono anche essere usati con le loro forme abbreviate, che sono molto utili per fornire le impostazioni predefinite:

$ x || = 0; # Se $ x era falso, ora ha un valore di 0.

$ x // = 0; # Se $ x non era definito, ora ha un valore pari a zero.

Cheerio,

Paolo


4
È un linguaggio così comune che difficilmente si qualifica come una caratteristica "nascosta".
Michael Carman,

3
peccato che la bella tipografa pensi // è un commento :)
John Ferguson,

2
Domanda, esiste una "funzione di utilizzo" per utilizzare questi nuovi operatori o sono abilitati per impostazione predefinita? Sto ancora appoggiando le funzionalità di Perl 5.10.
JJ,

6
// è presente per impostazione predefinita, non sono necessarie modifiche speciali. Puoi anche eseguire il backport in 5.8.x con la dor-patch ... vedi la directory autori / id / H / HM / HMBRAND / su qualsiasi mirror CPAN. FreeBSD 6.xe oltre lo fa per te nel loro pacchetto perl.
dland

2
Quando || oppure // è combinato con do {}, puoi incapsulare un compito più complesso, ovvero $ x = $ a || do {my $ z; 3 o 4 linee di derivazione; $ z};
RIT

39

Gli operatori ++ e unario - non funzionano solo sui numeri, ma anche sulle stringhe.

my $_ = "a"
print -$_

stampe -a

print ++$_

stampe b

$_ = 'z'
print ++$_

stampe aa


3
Per citare perlvar: "L'operatore di auto-decremento non è magico." Quindi --non funziona con le stringhe.
Moritz,

"aa" non sembra essere l'elemento naturale che segue "z". Mi aspetterei il prossimo valore ASCII più alto, che è "{".
Ether,

4
Non chiedere a un programmatore cosa viene dopo "z"; chiedi a un essere umano. Questa funzione è eccezionale per la numerazione degli elementi in un lungo elenco.
Barry Brown,

17
Quando ero nuovo in Perl, ho implementato questa funzione con il comportamento esatto da z a aa, quindi l'ho mostrata a un collega che ha riso e me e ha detto "lascia che ti mostri qualcosa". Ho pianto un po 'ma ho imparato qualcosa.
Copas,

2
@Ether - Se lo desideri, usa i numeri e convertili automaticamente in ASCII con ord(). Oppure, scrivi una piccola classe e sovraccarica gli operatori per farlo per te.
Chris Lutz,

36

Poiché Perl ha quasi tutte le parti "esoteriche" delle altre liste, ti dirò l'unica cosa che Perl non può:

L'unica cosa che Perl non può fare è avere URL arbitrari nudi nel codice, poiché l' //operatore viene utilizzato per le espressioni regolari.

Nel caso in cui non fosse ovvio per te quali funzionalità offre Perl, ecco un elenco selettivo delle voci forse non del tutto ovvie:

Dispositivo di Duff - in Perl

Portabilità e standardità - Probabilmente ci sono più computer con Perl che con un compilatore C.

Una classe di manipolazione di file / percorsi - File :: Find funziona su un numero ancora maggiore di sistemi operativi rispetto a .Net

Virgolette per elenchi e stringhe delimitati da spazi bianchi - Perl consente di scegliere virgolette quasi arbitrarie per l'elenco e i delimitatori di stringhe

Spazi dei nomi aliasable - Perl ha questi attraverso assegnazioni glob:

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

Inizializzatori statici - Perl può eseguire il codice in quasi tutte le fasi della compilazione e dell'istanza dell'oggetto, da BEGIN(analisi del codice) a CHECK(dopo l'analisi del codice import) a new(all'istanza del modulo) a (istanza dell'oggetto) a DESTROY(distruzione dell'oggetto) a END(uscita programma)

Le funzioni sono cittadini di prima classe, proprio come in Perl

Portata e chiusura del blocco - Perl ha entrambe

Chiamare metodi e accessori indirettamente tramite una variabile - Anche Perl lo fa:

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

Definizione dei metodi tramite il codice - Perl consente anche questo :

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

Pervasive documentazione in linea - la documentazione Perl è in linea e probabilmente sul vostro sistema troppo

Metodi magici che vengono chiamati ogni volta che chiami una funzione "inesistente" - Perl lo implementa nella funzione AUTOLOAD

Riferimenti simbolici - si consiglia vivamente di starne alla larga. Mangeranno i tuoi figli. Ma, naturalmente, Perl ti consente di offrire ai tuoi figli demoni assetati di sangue.

Scambio di un valore di riga : Perl consente l'assegnazione dell'elenco

Possibilità di sostituire anche le funzioni principali con le proprie funzionalità

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

o

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

unlink($_) for @ARGV

Sono un fan della documentazione di Perl rispetto ad altre lingue, ma penso ancora che per Regexes e riferimenti potrebbe essere molto razionalizzato. ad esempio, il miglior primer per regex non è Perlre, ma Perlop
John Ferguson,

9
"L'unica cosa che Perl non può fare è avere URL arbitrari nudi nel codice, poiché l'operatore // viene utilizzato per le espressioni regolari." - questa è una totale assurdità.

Grazie per la tua comprensione. Ho esaminato alcuni modi per avere un URL http: // ... nudo nel codice Perl senza utilizzare un filtro di origine e non ho trovato un modo. Potresti mostrare come è possibile? // è usato per le espressioni regolari nelle versioni Perl fino a 5.8.x. In 5.10 è riproposto per definito o assegnato.
Corion,

8
Perché / dove ti vuole URL nudi nel codice? Non riesco a pensare a un esempio.
naufrago l'

18
Nessuno lo vorrebbe, è solo un meme Java. " foo.com " è l'etichetta http: e quindi "foo.com" in un commento. Alcune persone lo trovano interessante perché ... sono stupidi.
jrockway,

35

Autovivificazione . AFAIK nessun'altra lingua ce l'ha .


Non avevo idea che Python, et al, non lo supportassero.
skiphoppy,

@davidnicol: Davvero? Puoi fornire un collegamento? La mia rapida ricerca su Google non ha restituito nulla. Per coloro che non conoscono ECMAscript è il nome corretto per Javascript. en.wikipedia.org/wiki/ECMAScript
JJ

1
E c'è un modulo per disabilitare l'autovivication
Alexandr Ciornii,

1
@Gregg Lind - Dato che Python crea automaticamente variabili ogni volta che le assegni per la prima volta, l'autovivificazione creerebbe problemi mostruosi da un singolo errore di battitura.
Chris Lutz,

3
@tchrist - a = [[x * y for y in xrange (1,11)] for x in xrange (1,11)]
Onnipotente

31

È semplice citare quasi ogni tipo di strana stringa in Perl.

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

In effetti, i vari meccanismi di quotazione in Perl sono piuttosto interessanti. I meccanismi di quotazione simili a regex del Perl consentono di citare qualsiasi cosa, specificando i delimitatori. Puoi usare quasi tutti i caratteri speciali come #, / o apri / chiudi caratteri come (), [] o {}. Esempi:

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.);

Meccanismi di citazione:

q: citazione letterale; l'unico personaggio che deve essere evaso è il carattere finale. qq: una citazione interpretata; elabora le variabili e scappa i caratteri. Ottimo per le stringhe che devi citare:

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

qx: funziona come qq, ma poi lo esegue come comando di sistema, in modo non interattivo. Restituisce tutto il testo generato dallo standard. (Anche il reindirizzamento, se supportato nel sistema operativo, viene rilasciato) Anche con virgolette (il carattere `).

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

qr: interpreta come qq, ma poi lo compila come espressione regolare. Funziona anche con le varie opzioni su regex. Ora puoi passare la regex come variabile:

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 operatore di quotazioni molto, molto utile. Trasforma un insieme citato di parole separate da spazi bianchi in un elenco. Ottimo per compilare i dati in un test unitario.


   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) ]; 

Sono fantastici da usarli ogni volta che rende le cose più chiare. Per qx, qq e q, molto probabilmente uso gli operatori {}. L'abitudine più comune delle persone che usano qw è di solito l'operatore (), ma a volte vedi anche qw //.


1
A volte uso qw "" in modo che gli evidenziatori della sintassi lo evidenzino correttamente.
Brad Gilbert,

Funziona per me in SlickEdit. :)
Robert P,

1
@fengshaun, gli editori mi usano generalmente do evidenziare queste correttamente. Mi riferivo, in parte, all'evidenziatore della sintassi su StackOverflow.
Brad Gilbert,

@Brad Gilbert: Stack Overflow non può (beh, (non) analizzare Perl degno di cattivo lavoro. ☹
tchrist

my $moreout = qx{type "$path" 2>&1};... Non sapevo che potresti farlo! [TM]
dland il

27

Non proprio nascosto, ma molti programmatori Perl ogni giorno non conoscono CPAN . Ciò vale soprattutto per le persone che non sono programmatori a tempo pieno o che non programmano in Perl a tempo pieno.


27

L'istruzione "for" può essere utilizzata nello stesso modo in cui "con" è utilizzato in Pascal:

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

È possibile applicare una sequenza di operazioni s ///, ecc. Alla stessa variabile senza dover ripetere il nome della variabile.

NOTA: lo spazio non interrotto sopra (& nbsp;) ha nascosto Unicode in esso per aggirare il Markdown. Non copiarlo incollalo :)


E "map" fa lo stesso trucco ... map {....} $ item; Uno dei vantaggi dell'utilizzo di "per" sulla "mappa" sarebbe che potresti usare il prossimo per scoppiare.
Draegtun,

2
Inoltre, poiché l'oggetto manipolato è elencato prima che il codice esegua la manipolazione, portando a una migliore leggibilità.
Robert P,

@RobertP: Esatto. Un attualizzatore è utile nel discorso.
tchrist,

26

L'operatore quoteword è una delle mie cose preferite. Confrontare:

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

e

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

Molto meno rumore, più facile per gli occhi. Un'altra cosa davvero bella di Perl, che manca davvero quando si scrive SQL, è che una virgola finale è legale:

print 1, 2, 3, ;

Sembra strano, ma non se indenti il ​​codice in un altro modo:

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

L'aggiunta di un argomento aggiuntivo alla chiamata di funzione non richiede di armeggiare con virgole su righe precedenti o finali. Il cambio di linea singola non ha alcun impatto sulle linee circostanti.

Questo rende molto piacevole lavorare con funzioni variadiche. Questa è forse una delle caratteristiche più sottovalutate di Perl.


2
Un caso interessante della sintassi di Perl è che è valido quanto segue: per $ _ qw (un elenco di cose) {...}
effimero

1
Puoi persino abusare della sintassi globale per citare parole, purché non utilizzi caratteri speciali come * ?. Quindi puoi scriverefor (<a list of stuff>) { ... }
Moritz il

1
@ephemient: quasi. Funziona solo con i lessici: per il mio $ x qw (abc) {...} Ad esempio: per $ _ qw (abc) {print} # non stampa nulla
dland

perché aggiungere quel lessico extra quando puoi goderti il ​​default preferito di perl? per (qw / abcd /) {stampa; }
fengshaun,

2
@ephemient, @fengshaun, @moritz, @dland: è “riparato” in blead ; vedi questo thread p5p .
tchrist,

26

La possibilità di analizzare i dati direttamente incollati in un blocco DATA . Non è necessario salvare in un file di prova per essere aperto nel programma o simile. Per esempio:

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

__DATA__
some good data
some bad data
more good data 
more good data 

E molto utile in piccoli test!
fengshaun,

@peter mortensen come avresti più blocchi? E come si finisce un blocco?
Rospo

@Toad: è la risposta di Allan (vedi l'elenco delle revisioni). È meglio rivolgersi a quell'utente. Oppure, poiché quell'utente ha lasciato Stack Overflow, forse non si rivolge a nessuno in particolare (quindi un vero esperto Perl può risolverlo in seguito).
Peter Mortensen,

3
@Hai: No, è non è brutta - in realtà, è esattamente l'opposto di brutto: è pulito, svelte, minimal, e bello; in una parola, è meraviglioso, e le lingue senza di essa sono una PITA. @peter mortensen, @toad: una risposta su come avere più blocchi di dati nello stesso programma è utilizzare il modulo Inline :: Files off CPAN.
tchrist,

Inline :: Files è implementato utilizzando i filtri di origine. C'è anche Data :: Sezione che fornisce più blocchi in linea e non utilizza i filtri di origine.
Prakash K,

24

Nuove operazioni di blocco

Direi che la possibilità di espandere la lingua, creando operazioni di pseudo blocco è una di queste.

  1. Dichiarate il prototipo per un sub indicando che accetta prima un riferimento di codice:

    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. Puoi quindi chiamarlo nel corpo in questo modo

    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::Dumperè un'altra gemma semi-nascosta.) Nota come non hai bisogno della subparola chiave davanti al blocco o della virgola prima dell'hash. Finisce per assomigliare molto a:map { } @list

Filtri sorgente

Inoltre, ci sono filtri di origine. Dove Perl ti passerà il codice in modo che tu possa manipolarlo. Sia questo, sia le operazioni di blocco, sono praticamente cose da non provare a casa.

Ho fatto alcune cose pulite con i filtri di origine, ad esempio come creare un linguaggio molto semplice per controllare il tempo, consentendo brevi battute Perl per alcuni processi decisionali:

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

Lib::TL dovrebbe solo cercare sia le "variabili" che le costanti, crearle e sostituirle secondo necessità.

Ancora una volta, i filtri di origine possono essere disordinati, ma sono potenti. Ma possono rovinare qualcosa di terribile nei debugger e persino gli avvisi possono essere stampati con numeri di riga errati. Ho smesso di usare Damian's Switch perché il debugger perderebbe tutta la capacità di dirmi dove ero veramente. Ma ho scoperto che puoi minimizzare il danno modificando piccole sezioni di codice, mantenendole sulla stessa linea.

Hook di segnale

Spesso è abbastanza fatto, ma non è poi così ovvio. Ecco un gestore di dadi che si rifugia su quello vecchio.

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

Ciò significa che ogni qualvolta un altro modulo nel codice vuole morire, devono venire da te (a meno che qualcun altro non esegua una sovrascrittura distruttiva $SIG{__DIE__}). E puoi essere avvisato che qualcuno fa qualcosa che è un errore.

Certo, per abbastanza cose puoi semplicemente usare un END { }blocco, se tutto ciò che vuoi fare è ripulire.

overload::constant

Puoi ispezionare letterali di un certo tipo in pacchetti che includono il tuo modulo. Ad esempio, se lo usi nel tuo importsub:

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

significherà che ogni numero intero superiore a 2 miliardi nei pacchetti chiamanti verrà modificato in un Math::BigIntoggetto. (Vedi sovraccarico :: costante ).

Letterali interi raggruppati

Mentre ci siamo. Perl ti permette di dividere grandi numeri in gruppi di tre cifre e ottenere comunque un intero analizzabile da esso. Nota 2_000_000_000sopra per 2 miliardi.


5
Quando si usano i gestori $ SIG { DIE }, si consiglia vivamente di ispezionare $ ^ S per vedere se il programma sta effettivamente morendo, o semplicemente lanciare un'eccezione che verrà catturata. Di solito non vuoi interferire con quest'ultimo.
pjf,

Il nuovo blocco è molto istruttivo! Pensavo fosse una lingua semantica! grazie molto.
ZeroCool

Un uso istruttivo del filtro sorgente è NiceSlice di pdl ( pdl.perl.org/?docs=NiceSlice&title=PDL::NiceSlice ) in modo che non sia necessario utilizzare il ->slicemetodo ogni volta che è necessario un slice.
Joel Berger,

24

La "x" binaria è l' operatore di ripetizione :

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

Funziona anche con elenchi:

print for (1, 4, 9) x 3; # print 149149149

Questo è uno dei motivi per cui Perl è stato così popolare tra gli hacker. perl -e 'stampa 0x000 x 25';
JJ,

4
Il mio uso preferito per questo è generare segnaposto per l'ultima parte di un'istruzione INSERT SQL: @p = ('?') X $ n; $ p = join (",", @p); $ sql = "INSERISCI ... VALORI ($ p)";
skiphoppy,

24

Controllo della contaminazione. Con il controllo della contaminazione abilitato, perl morirà (o avviserà, con -t) se si tenta di passare i dati contaminati (approssimativamente parlando, dati dall'esterno del programma) a una funzione non sicura (apertura di un file, esecuzione di un comando esterno, ecc.). È molto utile quando si scrivono script setuid o CGI o qualsiasi cosa in cui lo script abbia privilegi maggiori rispetto alla persona che lo fornisce.

Goto magico. goto &subeffettua una chiamata di coda ottimizzata.

Il debugger.

use stricte use warnings. Questi possono salvarti da un mucchio di errori di battitura.


1
Perché altre lingue non hanno questa funzione? Questa funzione utilizzata rende gli script Web Perl un ordine di grandezza più sicuri.
Matthew Lock,

22

In base al modo in cui gli switch "-n"e "-p"sono implementati in Perl 5, puoi scrivere un programma apparentemente errato che include }{:

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

che viene convertito internamente in questo codice:

LINE: while (defined($_ = <ARGV>)) {
    print $_; }{ print "$. Files";
}

@martin clayton: perché si chiama così?
tchrist,

@tchrist - perché, presumibilmente, sembra che due persone si stiano sfregando il naso. Di profilo, se vedi cosa intendo.
Martin Clayton,

18

Cominciamo facilmente con l' operatore dell'astronave .

$a = 5 <=> 7;  # $a is set to -1
$a = 7 <=> 5;  # $a is set to 1
$a = 6 <=> 6;  # $a is set to 0

1
@Leon: C / C ++ non restituisce un valore di 3 per i numeri. Se la memoria serve a funzioni String Comapre sono gli unici 3 valori restituiti che conosco nell'intero linguaggio STL. AFAIK Python non ha un confronto numerico di 3 resi. Java non ha neanche un confronto di ritorno 3 specifico per numero.
JJ,

7
Vale la pena menzionare ciò che è così utile sugli operatori di confronto -1/0/1, dal momento che non tutti potrebbero saperlo: è possibile collegarli insieme all'operatore-or per eseguire primario / secondario / ecc. sorta. Quindi ($a->lname cmp $b->lname) || ($a->fname cmp $b->fname)ordina le persone in base al loro cognome, ma se due persone hanno lo stesso cognome, verranno ordinate in base al loro nome.
Hobbs,

@JJ Python ha un confronto di 3 valori: cmp () >>> print (cmp (5,7), cmp (6,6), cmp (7,5)) (-1, 0, 1)
bukzor

18

Questa è una meta-risposta, ma gli archivi Perl Tips contengono tutti i tipi di trucchi interessanti che possono essere fatti con Perl. L'archivio dei suggerimenti precedenti è on-line per la navigazione e può essere sottoscritto tramite mailing list o atom feed.

Alcuni dei miei consigli preferiti includono la creazione di file eseguibili con PAR , l' utilizzo di autodie per generare automaticamente eccezioni e l'uso dello switch e dei costrutti smart-match in Perl 5.10.

Divulgazione: sono uno degli autori e manutentori di Perl Tips, quindi ovviamente penso molto bene a loro. ;)


2
È probabilmente una delle lingue meglio documentate in circolazione e imposta il modello di strumenti per la ricerca della documentazione. Che l'elenco in questa domanda non è probabilmente necessario come per altre lingue.
Axeman,

1
autodie sembra molto bello.
j_random_hacker,

18

mappa - non solo perché rende il proprio codice più espressivo, ma perché mi ha dato l'impulso di leggere qualcosa in più su questa "programmazione funzionale".


15

La clausola continue sui loop. Verrà eseguito nella parte inferiore di ogni loop, anche quelli che verranno seguiti.

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

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

  print "bottom of loop\n";
}continue{
  print "continue\n";
}

15

Il mio voto andrebbe per i gruppi (? {}) E (?? {}) nelle espressioni regolari di Perl. Il primo esegue il codice Perl, ignorando il valore restituito, il secondo esegue il codice, usando il valore restituito come espressione regolare.


perl ha inventato così tante estensioni regexp che altri programmi ora usano spesso pcre (perl regex compatibile) invece del linguaggio regex originale.
Sec

Leggi il piccolo sobborgo qui perldoc.perl.org/… :-D
JJ

Perl ha davvero (per quanto ne so), in testa al gruppo, quando si tratta di regexps.
Brad Gilbert,

Questo, per quanto ne so, è ancora sperimentale e potrebbe non funzionare allo stesso modo in Perls futuri. Per non dire che non è utile, ma una versione leggermente più sicura e altrettanto utile può essere trovata nel flag s /// command's / e: s/(pattern)/reverse($1);/ge;# inverte tutto patterns.
Chris Lutz,

@Chris Lutz, @Leon Timmerman: Nota che quei due costrutti sono ora reëntrant. Si noti inoltre che il secondo non deve più essere utilizzato per effettuare schemi ricorsivi, ora che possiamo ricorrere ai gruppi di acquisizione. @ Brad Gilbert: Esatto, anche se PCRE fa un buon lavoro nel seguirci; un'area di eccellenza regex in cui Perl è completamente incontrastata è il suo accesso alle proprietà Unicode; vedere la mia distribuzione unitaria di uninames, unicharse soprattutto unipropsper vedere solo una parte di ciò che intendo.
tchrist,

13
while(/\G(\b\w*\b)/g) {
     print "$1\n";
}

l'ancora \ G. Fa caldo .


3
... e indica la posizione della fine della partita precedente.
Dave Sherohman,

1
Ma devi chiamare la tua regex in un contesto scalare.
davidnicol,

@davidnicol: il codice sopra funziona. Puoi chiarire cosa intendi?
JJ,

13

L' m//operatore ha alcuni casi speciali oscuri:

  • Se lo usi ?come delimitatore, corrisponde solo una volta, a meno che non chiami reset.
  • Se si utilizza 'come delimitatore il modello non viene interpolato.
  • Se il modello è vuoto, utilizza il modello dell'ultima corrispondenza corretta.

2
Questi sono più simili a Gotcha nascosti che a funzioni nascoste! Non conosco nessuno a cui piacciano. Un thread su p5p qualche tempo fa ha discusso dell'utilità di un putativo flag m / $ foo / r, dove / r significherebbe nessuna interpolazione (la lettera non è importante) dal momento che nessuno può mai ricordare la singola virgoletta.
dland

2
@dland: concordato; Chiamerei queste caratteristiche mis nascoste e non le userei mai nel codice di produzione.
Michael Carman,

7
Non riesco a immaginare che un programmatore Perl non sia in grado di ricordare (o persino di indovinare) che le virgolette singole non rappresentano interpolazione. Il suo utilizzo con questa semantica è quasi universale nella lingua che preferirei mi aspettassi che fosse così ...
Sundar - Reinstate Monica

e se il modello è vuoto e l'ultima corrispondenza corretta è stata compilata con il modificatore / o, da quel momento in poi verrà bloccato su quel modello.
davidnicol,

1
Penso che il comportamento del modello vuoto sia stato deprecato. Principalmente perché uno schema come m / $ foo / diventa un brutto bug quando $ foo è vuoto.
Matthew S,

12

L' operatore Null Filehandle Diamond<> ha il suo posto nella costruzione di strumenti da riga di comando. Si comporta come <FH>leggere da un handle, tranne per il fatto che seleziona magicamente quello che si trova per primo: i nomi dei file della riga di comando o STDIN. Tratto da perlop:

while (<>) {
...         # code for each line
}

4
Segue anche la semantica UNIX dell'uso di "-" per dire "letto da stdin. Quindi potresti farlo perl myscript.pl file1.txt - file2.txt, e perl elaborerebbe il primo file, quindi stdin, quindi il secondo file.
Ryan C. Thompson,

È possibile che overloadl' <>operatore sui propri oggetti ( <$var>) funzioni come un iteratore. Tuttavia non funziona come ci si potrebbe aspettare dal contesto dell'elenco.
dolmen,

11

Blocchi di codice speciali come BEGIN, CHECKe END. Provengono da Awk, ma funzionano in modo diverso in Perl, perché non è basato su record.

Il BEGINblocco può essere utilizzato per specificare del codice per la fase di analisi; viene anche eseguito quando si esegue il controllo della sintassi e della variabile perl -c. Ad esempio, per caricare le variabili di configurazione:

BEGIN {
    eval {
        require 'config.local.pl';
    };
    if ($@) {
        require 'config.default.pl';
    }
}

11
rename("$_.part", $_) for "data.txt";

rinomina data.txt.part in data.txt senza ripetere me stesso.


10

Un po 'oscuro è l' "operatore" tilde-tilde che forza il contesto scalare.

print ~~ localtime;

equivale a

print scalar localtime;

e diverso da

print localtime;

5
Ciò è particolarmente oscuro perché perl5.10.0 introduce anche l '"operatore di corrispondenza intelligente" ~~, che può fare corrispondenze regex, può vedere se un oggetto è contenuto in un array e così via.
Moritz,

Non è oscuro, è offuscato (e utile per il golf e i JAPH).
Michael Carman,

Questo non è corretto! ~~ non è sicuro sui riferimenti! Li stringe.
Leon Timmermans,

Beh si. La stringificazione è ciò che accade ai riferimenti quando viene forzato nel contesto scalare. In che modo ciò rende errato "~~ forza il contesto scalare"?
Dave Sherohman,

3
@Nomad Dervish: contesto scalare / = stringificazione. ad esempio "$ n = @a" è un contesto scalare. "$ s = qq '@ a'" è una stringa. Per quanto riguarda i riferimenti, "$ ref1 = $ ref2" è un contesto scalare, ma non stringe.
Michael Carman,

9

pareggio, l'interfaccia di legatura variabile.


Cravatta :: File salvato la mia giornata una volta!
mhd,

9

La "modalità disperazione" dei costrutti di controllo del loop di Perl che li induce a cercare nello stack per trovare un'etichetta corrispondente consente alcuni comportamenti curiosi di cui Test :: More trae vantaggio, nel bene e nel male.

SKIP: {
    skip() if $something;

    print "Never printed";
}

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

C'è il file .pmc poco conosciuto. "usa Foo" cercherà Foo.pmc in @INC prima di Foo.pm. Lo scopo era quello di consentire il caricamento iniziale del bytecode compilato, ma Module :: Compile ne approfitta per memorizzare nella cache i moduli filtrati di origine per tempi di caricamento più rapidi e debug più semplice.

La possibilità di trasformare gli avvisi in errori.

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

Questo è ciò a cui riesco a pensare dalla cima della mia testa che non è stato menzionato.


9

L'operatore capra *:

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

o

sub foo {
    return @_;
}

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

Funziona perché l'assegnazione dell'elenco nel contesto scalare produce il numero di elementi nell'elenco che viene assegnato.

* Nota, non proprio un operatore


Questo è il più (bene, il meno) bellissimo "operatore" di sempre.
Chris Lutz,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.