Versteckte Funktionen von Perl?


143

Was sind einige wirklich nützliche, aber esoterische Sprachfunktionen in Perl, die Sie tatsächlich einsetzen konnten, um nützliche Arbeit zu leisten?

Richtlinien:

  • Versuchen Sie, die Antworten auf den Perl-Kern und nicht auf CPAN zu beschränken
  • Bitte geben Sie ein Beispiel und eine kurze Beschreibung

Versteckte Funktionen finden Sie auch in den versteckten Funktionen anderer Sprachen:

(Dies sind alles aus Corions Antwort )

  • C.
    • Duffs Gerät
    • Portabilität und Standardität
  • C #
    • Anführungszeichen für durch Leerzeichen getrennte Listen und Zeichenfolgen
    • Aliasable Namespaces
  • Java
    • Statische Initialisierer
  • JavaScript
    • Funktionen sind Bürger erster Klasse
    • Blockumfang und Verschluss
    • Indirekter Aufruf von Methoden und Accessoren über eine Variable
  • Rubin
    • Methoden durch Code definieren
  • PHP
    • Durchdringende Online-Dokumentation
    • Magische Methoden
    • Symbolische Referenzen
  • Python
    • Ein Zeilenwert tauschen
    • Möglichkeit, auch Kernfunktionen durch eigene Funktionen zu ersetzen

Andere versteckte Funktionen:

Betreiber:

Konstrukte zitieren:

Syntax und Namen:

Module, Pragmas und Befehlszeilenoptionen:

Variablen:

Schleifen und Flusskontrolle:

Reguläre Ausdrücke:

Andere Eigenschaften:

Andere Tricks und Meta-Antworten:


Siehe auch:


Die meisten dieser Funktionen sind im täglichen Gebrauch, einige kommen in den meisten Perl-Skripten vor, und die meisten, die unter "Andere" aufgeführt sind, stammen noch aus anderen Sprachen. Diese "versteckten" Änderungen nennen die Absicht der Frage.
Reinierpost

Antworten:


54

Der Flip-Flop-Operator ist nützlich, um die erste Iteration zu überspringen, wenn Sie die von einem Dateihandle zurückgegebenen Datensätze (normalerweise Zeilen) durchlaufen, ohne eine Flag-Variable zu verwenden:

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

Führen Sie aus perldoc perlopund suchen Sie nach "Flip-Flop" für weitere Informationen und Beispiele.


Eigentlich ist das von Awk, wo Sie Flip-Flop zwischen zwei Mustern machen können, indem Sie Muster1, Muster2
Bruno De Fraine

15
Zur Verdeutlichung ist der "versteckte" Aspekt, dass, wenn einer der Operanden zum Skalar '..' eine Konstante ist, der Wert implizit mit der Eingabezeilennummer ($.) Verglichen wird
Michael Carman

47

Es gibt viele nicht offensichtliche Funktionen in Perl.

Wussten Sie zum Beispiel, dass nach einem Siegel ein Leerzeichen stehen kann?

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

Oder dass Sie untergeordnete numerische Namen vergeben können, wenn Sie symbolische Referenzen verwenden?

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

Es gibt auch den Quasi-Operator "bool", der 1 für wahre Ausdrücke und die leere Zeichenfolge für false zurückgibt:

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

Andere interessante Dinge: Mit können use overloadSie String-Literale und Zahlen überladen (und zum Beispiel BigInts oder was auch immer machen).

Viele dieser Dinge sind tatsächlich irgendwo dokumentiert oder folgen logisch den dokumentierten Funktionen, aber einige sind nicht sehr bekannt.

Update : Noch ein schönes. Im Folgenden wurden die q{...}zitierenden Konstrukte erwähnt, aber wussten Sie, dass Sie Buchstaben als Trennzeichen verwenden können?

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

Ebenso können Sie reguläre Ausdrücke schreiben:

m xabcx
# same as m/abc/

2
"Wussten Sie, dass es nach einem Siegel ein Leerzeichen geben kann?" Ich bin völlig verblüfft. Beeindruckend.
Aristoteles Pagaltzis

1
Cool! !! $ undef_var erstellt keine Warnung.
Axeman

4
Ich denke, Ihr Beispiel für die Verwendung von Buchstaben zur Abgrenzung von Zeichenfolgen sollte " Nur ein weiterer Perl-Hacker" sein und nicht "Jet ein weiterer Perl-Hacker" = P
Chris Lutz

Das Schlimmste ist, dass Sie auch andere Dinge als Begrenzer verwenden können. Sogar schließende Klammern. Folgendes ist gültig: s} Regex} Ersetzung} xsmg; q] String-Literal];
Ryan C. Thompson

46

Unterstützung für komprimierte Dateien über Magic ARGV hinzufügen :

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;

(Anführungszeichen um $ _, die erforderlich sind, um Dateinamen mit Shell-Metazeichen in zu verarbeiten)

Jetzt <>dekomprimiert die Funktion alle @ARGVDateien, die mit ".gz" oder ".Z" enden:

while (<>) {
    print;
}

2
Ich glaube nicht, dass Sie dem |im Ersatz entkommen müssen .
Chris Lutz

Ich starre darauf und kann nicht herausfinden, wie es funktioniert. Ab wann wird zcat |als Befehl zum Durchleiten analysiert?
Ether

1
@Ether => Das Erkennen von Rohren ist eine Funktion der beiden offenen Argumente, die der Diamantoperator verwendet, wenn er jede Datei in@ARGV
Eric Strom

40

Eine meiner Lieblingsfunktionen in Perl ist die Verwendung des Booleschen ||Operators, um zwischen einer Reihe von Auswahlmöglichkeiten zu wählen.

 $x = $a || $b;

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

Das heißt, man kann schreiben:

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

den ersten wahren Wert nehmen aus $a, $bund $c, oder einen Standardwert von 0sonst.

In Perl 5.10 gibt es auch den //Operator, der die linke Seite zurückgibt, wenn sie definiert ist, und die rechte Seite, wenn sie definiert ist. Die folgenden wählt der erste definierte Wert aus $a, $b, $c, oder 0anders:

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

Diese können auch mit ihren Kurzformblättern verwendet werden, die für die Bereitstellung von Standardeinstellungen sehr nützlich sind:

$ x || = 0; # Wenn $ x falsch war, hat es jetzt den Wert 0.

$ x // = 0; # Wenn $ x undefiniert war, hat es jetzt den Wert Null.

Cheerio,

Paul


4
Dies ist eine so verbreitete Redewendung, dass sie kaum als "verstecktes" Merkmal zu qualifizieren ist.
Michael Carman

3
Schade, dass der hübsche Drucker // für einen Kommentar hält :)
John Ferguson

2
Frage: Gibt es eine "Verwendungsfunktion", um diese neuen Operatoren zu verwenden, oder sind sie standardmäßig aktiviert? Ich lehne mich immer noch an die Funktionen von Perl 5.10.
JJ

6
// ist standardmäßig drin, es sind keine speziellen Anpassungen erforderlich. Sie können es auch mit dem dor-patch in 5.8.x zurückportieren ... siehe das Verzeichnis der Autoren / id / H / HM / HMBRAND / auf jedem CPAN-Spiegel. FreeBSD 6.x und höher erledigt dies für Sie in ihrem Perl-Paket.
Dland

2
Wenn || oder // mit do {} kombiniert wird, können Sie eine komplexere Zuordnung kapseln, dh $ x = $ a || mache {mein $ z; 3 oder 4 Ableitungslinien; $ z};
RET

39

Die Operatoren ++ und unary - arbeiten nicht nur mit Zahlen, sondern auch mit Zeichenfolgen.

my $_ = "a"
print -$_

druckt -a

print ++$_

Drucke b

$_ = 'z'
print ++$_

druckt aa


3
Um Perlvar zu zitieren: "Der Operator für die automatische Dekrementierung ist nicht magisch." Funktioniert --also nicht mit Saiten.
Moritz

"aa" scheint nicht das natürliche Element nach "z" zu sein. Ich würde den nächsthöheren ASCII-Wert erwarten, nämlich "{".
Ether

4
Fragen Sie keinen Programmierer, was nach "z" kommt. frage einen Menschen. Diese Funktion eignet sich hervorragend zum Nummerieren von Elementen in einer langen Liste.
Barry Brown

17
Als ich neu bei Perl war, habe ich diese Funktion selbst mit dem genauen Verhalten von z zu aa implementiert und sie dann einem Kollegen gezeigt, der lachte und mir sagte: "Lass mich dir etwas zeigen". Ich weinte ein bisschen, lernte aber etwas.
Copas

2
@Ether - Wenn Sie das möchten, verwenden Sie Zahlen und konvertieren Sie sie automatisch in ASCII mit ord(). Oder schreiben Sie eine kleine Klasse und überladen Sie die Operatoren, um dies für Sie zu tun.
Chris Lutz

36

Da Perl fast alle "esoterischen" Teile aus den anderen Listen hat, werde ich Ihnen das eine sagen, was Perl nicht kann:

Das einzige, was Perl nicht tun kann, ist, bloße beliebige URLs in Ihrem Code zu haben, da der //Operator für reguläre Ausdrücke verwendet wird.

Für den Fall, dass Ihnen nicht klar war, welche Funktionen Perl bietet, finden Sie hier eine Auswahlliste der möglicherweise nicht ganz offensichtlichen Einträge:

Duffs Gerät - in Perl

Portabilität und Standardität - Es gibt wahrscheinlich mehr Computer mit Perl als mit einem C-Compiler

Eine Datei- / Pfadmanipulationsklasse - File :: Find funktioniert unter noch mehr Betriebssystemen als .Net

Anführungszeichen für durch Leerzeichen getrennte Listen und Zeichenfolgen - Mit Perl können Sie nahezu beliebige Anführungszeichen für Ihre Listen- und Zeichenfolgenbegrenzer auswählen

Aliasable Namespaces - Perl hat diese durch Glob-Zuweisungen:

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

Statische Initialisierer - Perl kann Code in fast jeder Phase der Kompilierung und Objektinstanziierung ausführen, von BEGIN(Code-Analyse) über CHECK(nach Code-Analyse) bis import(beim Modulimport) bis new(Objekt-Instanziierung) bis DESTROY(Objektzerstörung) bis END(Programm-Exit).

Funktionen sind erstklassige Bürger - genau wie in Perl

Blockumfang und Verschluss - Perl hat beides

Indirekter Aufruf von Methoden und Accessoren über eine Variable - Perl macht das auch:

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

Methoden durch Code definieren - Perl erlaubt das auch :

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

Durchdringende Online-Dokumentation - Die Perl-Dokumentation ist online und wahrscheinlich auch auf Ihrem System

Magische Methoden , die aufgerufen werden, wenn Sie eine "nicht vorhandene" Funktion aufrufen - Perl implementiert dies in der AUTOLOAD-Funktion

Symbolische Hinweise - Sie sollten sich von diesen fernhalten. Sie werden deine Kinder essen. Aber natürlich können Sie mit Perl Ihren Kindern blutrünstige Dämonen anbieten.

Einzeiliger Wertaustausch - Perl ermöglicht die Listenzuweisung

Möglichkeit, auch Kernfunktionen durch eigene Funktionen zu ersetzen

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

oder

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

unlink($_) for @ARGV

Ich bin ein Fan von Perls Dokumentation im Vergleich zu anderen Sprachen, aber ich denke immer noch, dass Regexes und Referenzen viel rationalisiert werden könnten. zB ist der beste Primer für Regexes nicht Perlre, sondern Perlop
John Ferguson

9
"Das einzige, was Perl nicht tun kann, ist, bloße beliebige URLs in Ihrem Code zu haben, da der Operator // für reguläre Ausdrücke verwendet wird." - Das ist völliger Unsinn.

Vielen Dank für Ihren Einblick. Ich habe mir einige Möglichkeiten angesehen, eine nackte http: // ... URL im Perl-Code ohne Verwendung eines Quellfilters zu haben, und keinen Weg gefunden. Vielleicht können Sie zeigen, wie dies möglich ist? // wird für reguläre Ausdrücke in Perl-Versionen bis 5.8.x verwendet. In 5.10 wird es für definierte oder Zuweisungen verwendet.
Corion

8
Warum / wo werden Sie wollen nackte URLs in Ihrem Code? Ich kann mir kein Beispiel vorstellen.
Castaway

18
Niemand würde das wollen, es ist nur ein Java-Mem. " foo.com " ist das Label http: und dann "foo.com" in einem Kommentar. Einige Leute finden das interessant, weil ... sie dumm sind.
Jrockway

35

Autovivifizierung . AFAIK keine andere Sprache hat es .


Ich hatte keine Ahnung, dass Python et al. Dies nicht unterstützten.
Skiphoppy

@ Davididol: Wirklich? Können Sie einen Link bereitstellen? Meine schnelle Suche bei Google hat nichts zurückgegeben. Für diejenigen, die ECMAscript nicht kennen, ist der richtige Name für Javascript. en.wikipedia.org/wiki/ECMAScript
JJ

1
Und es gibt ein Modul zum Deaktivieren der automatischen Aktivierung
Alexandr Ciornii

1
@Gregg Lind - Da Python bei jeder ersten Zuweisung automatisch Variablen erstellt, würde die automatische Aktivierung aus einem einzigen Tippfehler monströse Probleme verursachen.
Chris Lutz

3
@tchrist - a = [[x * y für y in xrange (1,11)] für x in xrange (1,11)]
Omnifarious

31

Es ist einfach, fast jede Art von seltsamer Zeichenfolge in Perl zu zitieren.

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

Tatsächlich sind die verschiedenen Zitiermechanismen in Perl sehr interessant. Mit den Perl-Regex-ähnlichen Anführungszeichen können Sie alles unter Angabe der Trennzeichen zitieren. Sie können fast jedes Sonderzeichen wie #, / oder Open / Close-Zeichen wie (), [] oder {} verwenden. Beispiele:

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

Angebotsmechanismen:

q: wörtliches Zitat; Das einzige Zeichen, das maskiert werden muss, ist das Endzeichen. qq: ein interpretiertes Zitat; verarbeitet Variablen und Escapezeichen. Ideal für Zeichenfolgen, die Sie zitieren müssen:

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

qx: Funktioniert wie qq, führt es dann aber nicht interaktiv als Systembefehl aus. Gibt den gesamten vom Standard ausgegebenen Text zurück. (Die Umleitung wird, sofern sie im Betriebssystem unterstützt wird, ebenfalls ausgegeben.) Wird auch mit Anführungszeichen (das Zeichen `) ausgeführt.

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

qr: Interpretiert wie qq, kompiliert es dann aber als regulären Ausdruck. Funktioniert auch mit den verschiedenen Optionen auf dem regulären Ausdruck. Sie können den regulären Ausdruck jetzt als Variable weitergeben:

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: Ein sehr, sehr nützlicher Anführungszeichenoperator. Verwandelt einen zitierten Satz von durch Leerzeichen getrennten Wörtern in eine Liste. Ideal zum Ausfüllen von Daten in einem Unit-Test.


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

Sie sind großartig, wenn sie die Dinge klarer machen. Für qx, qq und q verwende ich höchstwahrscheinlich die Operatoren {}. Die häufigste Gewohnheit von Menschen, die qw verwenden, ist normalerweise der Operator (), aber manchmal sehen Sie auch qw //.


1
Ich benutze manchmal qw "", damit Syntax-Textmarker es richtig hervorheben.
Brad Gilbert

Funktioniert für mich in SlickEdit. :)
Robert P

1
@fengshaun, Die Editoren, die ich normalerweise benutze , markieren diese korrekt. Ich bezog mich teilweise auf den Syntax-Textmarker auf StackOverflow.
Brad Gilbert

@Brad Gilbert: Stack Overflow kann Perl nicht analysieren (naja, (nicht) analysieren. ☹
tchrist

my $moreout = qx{type "$path" 2>&1};... Ich wusste nicht, dass du das kannst! [TM]
Dland

27

Nicht wirklich versteckt, aber viele Perl-Programmierer wissen jeden Tag nichts über CPAN . Dies gilt insbesondere für Personen, die keine Vollzeitprogrammierer sind oder nicht in Vollzeit in Perl programmieren.


27

Die "for" -Anweisung kann genauso verwendet werden wie "with" in Pascal:

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

Sie können eine Folge von s /// Operationen usw. auf dieselbe Variable anwenden, ohne den Variablennamen wiederholen zu müssen.

HINWEIS: In dem nicht unterbrechenden Bereich darüber (& nbsp;) ist Unicode versteckt, um den Markdown zu umgehen. Nicht kopieren, einfügen :)


Und "map" macht den gleichen Trick auch ... map {....} $ item; Ein Vorteil der Verwendung von "für" gegenüber "Karte" wäre, dass Sie als nächstes ausbrechen könnten.
Draegtun

2
Außerdem wird für das zu manipulierende Element vor dem Code aufgeführt, der die Manipulation ausführt, was zu einer besseren Lesbarkeit führt.
Robert P

@ RobertP: Das ist ganz richtig. Ein Topicalizer ist im Diskurs nützlich.
Tchrist

26

Der Zitatwortoperator ist eines meiner Lieblingssachen. Vergleichen Sie:

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

und

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

Viel weniger Lärm, schont das Auge. Eine andere wirklich schöne Sache an Perl, die man beim Schreiben von SQL wirklich vermisst, ist, dass ein nachfolgendes Komma legal ist:

print 1, 2, 3, ;

Das sieht seltsam aus, aber nicht, wenn Sie den Code anders einrücken:

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

Wenn Sie dem Funktionsaufruf ein zusätzliches Argument hinzufügen, müssen Sie nicht mit Kommas in vorherigen oder nachfolgenden Zeilen herumspielen. Die Änderung einer einzelnen Linie hat keine Auswirkungen auf die umgebenden Linien.

Dies macht es sehr angenehm, mit verschiedenen Funktionen zu arbeiten. Dies ist möglicherweise eine der am meisten unterbewerteten Funktionen von Perl.


2
Ein interessanter Eckfall von Perls Syntax ist, dass Folgendes gültig ist: für $ _ qw (eine Liste von
Dingen

1
Sie können die Glob-Syntax sogar zum Zitieren von Wörtern missbrauchen, solange Sie keine Sonderzeichen wie *? Verwenden. So können Sie schreibenfor (<a list of stuff>) { ... }
Moritz

1
@ Ephemient: fast. Das funktioniert nur mit Lexika: für mein $ x qw (abc) {...} Zum Beispiel: für $ _ qw (abc) {print} # druckt nichts
dland

Warum diese zusätzliche Lexik hinzufügen, wenn Sie Perls Lieblingsstandard genießen können? für (qw / abcd /) {print; }
Fengshaun

2
@ephemient, @fengshaun, @moritz, @dland: Das ist in Blead "behoben" ; siehe diesen p5p-Thread .
Tchrist

26

Die Möglichkeit, Daten zu analysieren, die direkt in einen DATA- Block eingefügt wurden . Sie müssen nicht in einer Testdatei speichern, um sie im Programm oder ähnlichem zu öffnen. Beispielsweise:

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

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

Und sehr nützlich in kleinen Tests!
Fengshaun

@ Peter Mortensen Wie hätten Sie mehrere Blöcke? Und wie beendet man einen Block?
Kröte

@Toad: Es ist Allans Antwort (siehe die Revisionsliste). Es ist besser, diesen Benutzer anzusprechen. Oder, da dieser Benutzer Stack Overflow verlassen hat, wenden Sie sich möglicherweise an niemanden (damit ein echter Perl-Experte dies später korrigieren kann).
Peter Mortensen

3
@Hai: Nein, es ist nicht hässlich - tatsächlich ist es genau das Gegenteil von hässlich: Es ist sauber, schlank, minimal und schön; Mit einem Wort, es ist wunderbar und Sprachen ohne es sind eine PITA. @peter mortensen, @toad: Eine Antwort darauf, wie mehrere Datenblöcke im selben Programm gespeichert werden können, besteht darin, das Inline :: Files- Modul außerhalb von CPAN zu verwenden.
Tchrist

Inline :: Files wird mithilfe von Quellfiltern implementiert. Es gibt auch Data :: Section , der mehrere Inline-Blöcke bereitstellt und keine Quellfilter verwendet.
Prakash K

24

Neue Blockoperationen

Ich würde sagen, dass die Möglichkeit, die Sprache zu erweitern und Pseudoblockoperationen zu erstellen, eine ist.

  1. Sie deklarieren den Prototyp für ein Sub, der angibt, dass zuerst eine Code-Referenz erforderlich ist:

    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. Sie können es dann im Körper so nennen

    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 ist ein weiteres halb verstecktes Juwel.) Beachten Sie, dass Sie das subSchlüsselwort vor dem Block oder das Komma vor dem Hash nicht benötigen . Es sieht am Ende sehr ähnlich aus wie:map { } @list

Quellfilter

Es gibt auch Quellfilter. Wo Perl Ihnen den Code übergibt, damit Sie ihn bearbeiten können. Sowohl dies als auch die Blockoperationen sind so ziemlich Dinge, die man nicht zu Hause ausprobieren sollte.

Ich habe einige nette Dinge mit Quellfiltern gemacht, zum Beispiel das Erstellen einer sehr einfachen Sprache zum Überprüfen der Uhrzeit, die kurze Perl-Einzeiler für einige Entscheidungen zulässt:

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

Lib::TL Ich würde nur nach den "Variablen" und den Konstanten suchen, sie erstellen und sie nach Bedarf ersetzen.

Auch hier können Quellfilter chaotisch sein, sind aber leistungsstark. Aber sie können Debugger etwas Schreckliches durcheinander bringen - und sogar Warnungen können mit den falschen Zeilennummern gedruckt werden. Ich habe aufgehört, Damians Schalter zu benutzen weil der Debugger nicht mehr in der Lage war, mir zu sagen, wo ich wirklich war. Ich habe jedoch festgestellt, dass Sie den Schaden minimieren können, indem Sie kleine Codeabschnitte ändern und sie in derselben Zeile halten.

Signalhaken

Es wird oft genug gemacht, aber es ist nicht so offensichtlich. Hier ist ein Würfelführer, der sich auf den alten stützt.

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

Das heißt, wenn ein anderes Modul im Code sterben möchte, muss es zu Ihnen kommen (es sei denn, jemand anderes führt ein destruktives Überschreiben durch $SIG{__DIE__} ). Und Sie können benachrichtigt werden, dass jemand etwas falsch macht.

Natürlich können Sie für genügend Dinge nur einen END { }Block verwenden, wenn Sie nur aufräumen möchten.

overload::constant

Sie können Literale eines bestimmten Typs in Paketen überprüfen, die Ihr Modul enthalten. Wenn Sie dies beispielsweise in Ihrem importSub verwenden:

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

Dies bedeutet, dass jede Ganzzahl, die größer als 2 Milliarden in den aufrufenden Paketen ist, in ein Math::BigIntObjekt geändert wird. (Siehe Überladung :: Konstante ).

Gruppierte Integer-Literale

Während wir dabei sind. Mit Perl können Sie große Zahlen in dreistellige Gruppen aufteilen und trotzdem eine analysierbare Ganzzahl daraus erhalten. Anmerkung 2_000_000_000oben für 2 Milliarden.


5
Wenn Sie $ SIG { DIE } -Handler verwenden, wird dringend empfohlen, $ ^ S zu überprüfen, um festzustellen, ob Ihr Programm tatsächlich stirbt, oder nur eine Ausnahme auszulösen, die abgefangen wird. Normalerweise möchten Sie Letzteres nicht stören.
pjf

Der neue Block ist sehr lehrreich! Ich dachte, es sei eine Sprachsemantik! Danke vielmals.
ZeroCool

Eine lehrreiche Verwendung des Quellfilters ist pdls NiceSlice ( pdl.perl.org/?docs=NiceSlice&title=PDL::NiceSlice ), sodass Sie das nicht ->slicejedes Mal als Methode verwenden müssen, wenn ein Slice benötigt wird.
Joel Berger

24

Binäres "x" ist der Wiederholungsoperator :

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

Es funktioniert auch mit Listen:

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

Dies ist ein Grund, warum Perl bei Hackern so beliebt ist. perl -e 'print 0x000 x 25';
JJ

4
Meine bevorzugte Verwendung hierfür ist das Generieren von Platzhaltern für den letzten Teil einer SQL INSERT-Anweisung: @p = ('?') X $ n; $ p = join (",", @p); $ sql = "INSERT ... VALUES ($ p)";
Skiphoppy

24

Verschmutzungsprüfung. Wenn die Verschmutzungsprüfung aktiviert ist, stirbt Perl (oder warnt mit-tWenn die ), wenn Sie versuchen, verdorbene Daten (grob gesagt Daten von außerhalb des Programms) an eine unsichere Funktion zu übergeben (Öffnen einer Datei, Ausführen eines externen Befehls usw.). Dies ist sehr hilfreich, wenn Sie Setuid-Skripte oder CGIs schreiben oder wenn das Skript über größere Berechtigungen verfügt als die Person, die es mit Daten versorgt.

Magie gehe. goto &subführt einen optimierten Tail Call durch.

Der Debugger.

use strictund use warnings. Diese können Sie vor einer Reihe von Tippfehlern bewahren.


1
Warum haben andere Sprachen diese Funktion nicht? Diese Funktion macht Perl-Web-Skripte um eine Größenordnung sicherer.
Matthew Lock

22

Basierend auf der Art "-n"und Weise der und"-p" Schalter in Perl 5 implementiert sind, können Sie ein scheinbar falsches Programm schreiben, einschließlich }{:

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

welches intern in diesen Code konvertiert wird:

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

@martin Clayton: Warum heißt es so?
Tchrist

@tchrist - weil es angeblich so aussieht, als würden sich zwei Leute die Nase reiben. Im Profil, wenn Sie sehen, was ich meine.
Martin Clayton

18

Beginnen wir einfach mit dem Raumschiff-Operator .

$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 ++ gibt keine 3-Wert-Rückgabe für Zahlen durch. Wenn Speicher dient, sind String-Comapre-Funktionen die einzigen 3-Wert-Rückgaben, die mir in der gesamten STL-Sprache bekannt sind. AFAIK Python hat keinen numerischen Vergleich mit 3 Rückgaben. Java hat auch keinen nummerenspezifischen 3-Return-Vergleich.
JJ

7
Es ist erwähnenswert, was an -1/0/1 Vergleichsoperatoren so nützlich ist, da möglicherweise nicht jeder weiß: Sie können sie mit dem or-Operator verketten, um primäre / sekundäre / etc. Sorten. So ($a->lname cmp $b->lname) || ($a->fname cmp $b->fname)sortiert Menschen , die von ihren Nachnamen, aber wenn zwei Personen den gleichen Nachnamen haben , dann werden sie mit dem Vornamen bestellt werden.
Hobbs

@JJ Python hat einen 3-Werte-Vergleich: cmp () >>> print (cmp (5,7), cmp (6,6), cmp (7,5)) (-1, 0, 1)
bukzor

18

Dies ist eine Meta-Antwort, aber die Perl-Tipps Archive enthalten alle möglichen interessanten Tricks, die mit Perl ausgeführt werden können. Das Archiv der vorherigen Tipps ist online zum Durchsuchen und kann über eine Mailingliste oder einen Atom-Feed abonniert werden.

Einige meiner besten Tipps umfassen den Aufbau Executables mit PAR , mit autodie Ausnahmen automatisch zu werfen , und die Verwendung der Schalter und Smart-match - Konstrukte in Perl 5.10.

Offenlegung: Ich bin einer der Autoren und Betreuer von Perl-Tipps, daher schätze ich sie offensichtlich sehr. ;)


2
Es ist wahrscheinlich eine der am besten dokumentierten Sprachen auf dem Markt und legt das Muster für Tools zum Durchsuchen der Dokumentation fest. Dass die Liste in dieser Frage wahrscheinlich nicht so benötigt wird wie für andere Sprachen.
Axeman

1
autodie sieht sehr gut aus.
j_random_hacker

18

map - nicht nur, weil es den eigenen Code ausdrucksvoller macht, sondern weil es mir den Impuls gab, ein bisschen mehr über diese "funktionale Programmierung" zu lesen.


15

Die continue-Klausel für Schleifen. Es wird am Ende jeder Schleife ausgeführt, auch bei den nächsten.

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

Meine Stimme würde für die Gruppen (? {}) Und (?? {}) in Perls regulären Ausdrücken gehen. Der erste führt Perl-Code aus, wobei der Rückgabewert ignoriert wird, der zweite führt Code aus und verwendet den Rückgabewert als regulären Ausdruck.


Perl hat so viele Regexp-Erweiterungen erfunden, dass andere Programme heute häufig pcre (Perl-kompatibler Regex) anstelle der ursprünglichen Regex-Sprache verwenden.
Sec

Lesen Sie den kleinen Klappentext hier perldoc.perl.org/… :-D
JJ

Perl hat wirklich (soweit ich weiß) die Nase vorn, wenn es um Regexps geht.
Brad Gilbert

Soweit mir bekannt ist, ist dies noch experimentell und funktioniert in zukünftigen Perls möglicherweise nicht mehr so. Um nicht zu sagen, dass es nicht nützlich ist, aber eine etwas sicherere und ebenso brauchbare Version finden Sie im / e-Flag des Befehls s ///: s/(pattern)/reverse($1);/ge;# kehrt alles um patterns.
Chris Lutz

@ Chris Lutz, @ Leon Timmerman: Beachten Sie, dass diese beiden Konstrukte jetzt wieder verfügbar sind. Beachten Sie auch, dass das zweite nicht mehr verwendet werden muss, um rekursive Muster zu bewirken, da wir jetzt auf Erfassungsgruppen zurückgreifen können. @Brad Gilbert: Das stimmt, obwohl PCRE uns ordentlich verfolgt. Ein Bereich von Regex Excellence, in dem Perl völlig unangefochten ist, ist der Zugriff auf Unicode-Eigenschaften. Sehen Sie meine Unitrio-Verteilung von uninames, unicharsund vor allem uniprops, um nur einen Teil dessen zu sehen, was ich meine.
Tchrist

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

der \ G Anker. Es ist heiß .


3
... und zeigt die Position des Endes des vorherigen Spiels an.
Dave Sherohman

1
Sie müssen Ihren regulären Ausdruck jedoch im skalaren Kontext aufrufen.
Davidnicol

@davidnicol: Der obige Code funktioniert. Können Sie klarstellen, was Sie meinen?
JJ

13

Der m//Bediener hat einige obskure Sonderfälle:

  • Wenn Sie ?als Trennzeichen verwenden, stimmt es nur einmal überein, es sei denn, Sie rufen an reset.
  • Wenn Sie 'als Trennzeichen verwenden, wird das Muster nicht interpoliert.
  • Wenn das Muster leer ist, wird das Muster aus der letzten erfolgreichen Übereinstimmung verwendet.

2
Dies sind eher versteckte Fallstricke als versteckte Funktionen! Ich kenne niemanden, der sie mag. Ein Thread auf p5p vor einiger Zeit diskutierte die Nützlichkeit eines mutmaßlichen m / $ foo / r-Flags, wobei / r keine Interpolation bedeuten würde (der Buchstabe ist nicht wichtig), da sich niemand jemals an die Sache mit einfachen Anführungszeichen erinnern kann.
Dland

2
@dland: Einverstanden; Ich würde diese versteckten Fehlfunktionen nennen und sie niemals im Produktionscode verwenden.
Michael Carman

7
Ich kann mir nicht vorstellen, dass ein Perl-Programmierer sich nicht erinnern (oder sogar erraten) kann, dass einfache Anführungszeichen für keine Interpolation stehen. Seine Verwendung mit dieser Semantik ist fast universell in der Sprache, die ich eher erwarten würde, dass dies so ist ...
sundar - Reinstate Monica

und wenn das Muster leer ist und die letzte erfolgreiche Übereinstimmung mit dem Modifikator / o kompiliert wurde, bleibt es von da an auf diesem Muster hängen.
Davidnicol

1
Ich denke, das Verhalten bei leeren Mustern ist veraltet. In erster Linie, weil ein Muster wie m / $ foo / zu einem bösen Fehler wird, wenn $ foo leer ist.
Matthew S

12

Der Null-Dateihandle- Diamantoperator <> hat seinen Platz beim Erstellen von Befehlszeilenwerkzeugen. Es verhält sich wie <FH>das Lesen aus einem Handle, mit der Ausnahme, dass es auf magische Weise auswählt, was zuerst gefunden wird: Befehlszeilendateinamen oder STDIN. Entnommen aus Perlop:

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

4
Es folgt auch der UNIX-Semantik, "-" zu verwenden, um "von stdin lesen" zu bedeuten. Sie könnten also tun perl myscript.pl file1.txt - file2.txt, und Perl würde die erste Datei verarbeiten, dann stdin, dann die zweite Datei.
Ryan C. Thompson

Sie können overloadden <>Operator für Ihre eigenen Objekte ( <$var>) wie einen Iterator verwenden. Es funktioniert jedoch nicht wie im Listenkontext zu erwarten.
Dolmen

11

Spezielle Codeblöcke wie BEGIN, CHECKund END. Sie kommen von Awk, funktionieren aber in Perl anders, weil es nicht auf Aufzeichnungen basiert.

Der BEGINBlock kann verwendet werden, um Code für die Analysephase anzugeben. Es wird auch ausgeführt, wenn Sie die Syntax- und Variablenprüfung durchführen perl -c. Zum Laden von Konfigurationsvariablen:

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

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

benennt data.txt.part in data.txt um, ohne mich wiederholen zu müssen.


10

Ein bisschen dunkel ist der Tilde-Tilde- "Operator", der den skalaren Kontext erzwingt.

print ~~ localtime;

ist das gleiche wie

print scalar localtime;

und anders als

print localtime;

5
Dies ist besonders unklar, da perl5.10.0 auch den "Smart Match Operator" einführt ~~, der Regex-Übereinstimmungen ausführen kann, prüfen kann, ob ein Element in einem Array enthalten ist und so weiter.
Moritz

Das ist nicht dunkel, das ist verschleiert (und nützlich für Golf und JAPHs).
Michael Carman

Das ist nicht richtig! ~~ ist nicht sicher auf Referenzen! Es fesselt sie.
Leon Timmermans

Nun ja. Stringifizierung ist das, was mit Referenzen passiert, wenn sie in einen skalaren Kontext gezwungen werden. Wie macht das "~~ erzwingt skalaren Kontext" falsch?
Dave Sherohman

3
@ Nomad Dervish: Skalarer Kontext / = Stringifizierung. zB "$ n = @a" ist ein skalarer Kontext. "$ s = qq '@ a'" ist eine Stringifizierung. In Bezug auf Referenzen ist "$ ref1 = $ ref2" ein skalarer Kontext, der jedoch nicht stringifiziert.
Michael Carman


9

Der "Verzweiflungsmodus" von Perls Schleifensteuerungskonstrukten, der sie veranlasst, den Stapel nachzuschlagen, um ein passendes Etikett zu finden, ermöglicht einige merkwürdige Verhaltensweisen, die Test :: More zum Guten oder Schlechten ausnutzt.

SKIP: {
    skip() if $something;

    print "Never printed";
}

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

Es gibt die wenig bekannte PMC-Datei. "use Foo" sucht in FIN.pmc in @INC vor Foo.pm. Dies sollte ermöglichen, dass zuerst kompilierter Bytecode geladen wird, aber Module :: Compile nutzt dies jedoch, um quellgefilterte Module für schnellere Ladezeiten und einfacheres Debuggen zwischenzuspeichern.

Die Fähigkeit, Warnungen in Fehler umzuwandeln.

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

Das ist es, woran ich denken kann, was nicht erwähnt wurde.


9

Der Ziegenbetreiber *:

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

oder

sub foo {
    return @_;
}

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

Dies funktioniert, weil die Listenzuweisung im skalaren Kontext die Anzahl der Elemente in der Liste ergibt, die zugewiesen werden.

* Beachten Sie, nicht wirklich ein Operator


Das ist der schönste "Operator" aller Zeiten.
Chris Lutz
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.