Ukryte cechy Perla?


143

Jakie są naprawdę przydatne, ale ezoteryczne funkcje językowe w Perlu, które faktycznie udało ci się wykorzystać do wykonania pożytecznej pracy?

Wytyczne:

  • Spróbuj ograniczyć odpowiedzi do rdzenia Perla, a nie do CPAN
  • Proszę podać przykład i krótki opis

Ukryte funkcje można znaleźć również w ukrytych funkcjach innych języków:

(To wszystko z odpowiedzi Coriona )

  • do
    • Urządzenie Duffa
    • Przenośność i standardowość
  • DO#
    • Cudzysłowy dla list i ciągów znaków rozdzielanych spacjami
    • Aliasable przestrzeni nazw
  • Jawa
    • Statyczne inicjatory
  • JavaScript
    • Funkcjonariusze są obywatelami pierwszej klasy
    • Zakres blokowy i zamknięcie
    • Wywoływanie metod i metod dostępu pośrednio przez zmienną
  • Rubin
    • Definiowanie metod za pomocą kodu
  • PHP
    • Wszechstronna dokumentacja online
    • Metody magiczne
    • Symboliczne odniesienia
  • Pyton
    • Zamiana wartości w jednym wierszu
    • Możliwość zastąpienia nawet podstawowych funkcji własną funkcjonalnością

Inne ukryte funkcje:

Operatorzy:

Cytowanie konstrukcji:

Składnia i nazwy:

Moduły, Pragmy i opcje wiersza poleceń:

Zmienne:

Pętle i kontrola przepływu:

Wyrażenia regularne:

Inne funkcje:

Inne sztuczki i meta-odpowiedzi:


Zobacz też:


Większość z tych funkcji jest w codziennym użyciu, niektóre występują w większości skryptów Perla, a większość z nich w sekcji „Inne” nadal wywodzi się z innych języków, nazywając je „ukrytymi”, zmienia cel pytania.
reinierpost

Odpowiedzi:


54

Operator flip-flop jest przydatny do pomijania pierwszej iteracji podczas przeglądania rekordów (zwykle linii) zwracanych przez uchwyt pliku, bez użycia zmiennej flag:

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

Uruchom perldoc perlopi wyszukaj „flip-flop”, aby uzyskać więcej informacji i przykładów.


Właściwie to pochodzi z Awk, gdzie możesz robić flip-flop między dwoma wzorami, pisząc pattern1, pattern2
Bruno De Fraine

15
Aby wyjaśnić, „ukryty” aspekt tego polega na tym, że jeśli którykolwiek z operandów do skalarnego „..” jest stałą, wartość jest niejawnie porównywana z numerem wiersza wejściowego ($.)
Michael Carman

47

W Perlu jest wiele nieoczywistych funkcji.

Na przykład, czy wiesz, że po sigilu może być spacja?

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

Albo że możesz podać nazwy numeryczne subskrybentów, jeśli używasz odniesień symbolicznych?

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

Istnieje również operator quasi „bool”, który zwraca 1 dla prawdziwych wyrażeń i pusty ciąg dla fałszu:

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

Inne interesujące rzeczy: za pomocą use overloadmożesz przeciążać literały ciągów i liczby (i na przykład uczynić je BigInts lub cokolwiek innego).

Wiele z tych rzeczy jest gdzieś udokumentowanych lub logicznie wynika z udokumentowanych cech, niemniej jednak niektóre nie są zbyt dobrze znane.

Aktualizacja : Kolejna fajna. Poniżej wymieniono q{...}konstrukcje cytowania, ale czy wiesz, że możesz używać liter jako separatorów?

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

Podobnie możesz pisać wyrażenia regularne:

m xabcx
# same as m/abc/

2
„Czy wiesz, że po sigilu może być spacja?” Jestem całkowicie zdumiony. Łał.
Arystoteles Pagaltzis

1
Chłodny! !! $ undef_var nie tworzy ostrzeżenia.
Axeman

4
Myślę, że Twój przykład użycia liter do oddzielenia ciągów powinien brzmieć „ Po prostu kolejny haker perla”, a nie „Odrzuć innego hakera perla” = P
Chris Lutz

Najgorsze jest to, że jako separatorów możesz też użyć innych elementów. Nawet nawiasy zamykające. Prawidłowe są następujące: s} regex} zamiennik} xsmg; q] literał łańcuchowy];
Ryan C. Thompson

46

Dodaj obsługę skompresowanych plików przez 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;

(cytuje wokół $ _ niezbędne do obsługi nazw plików z metaznakami powłoki w)

Teraz <>funkcja zdekompresuje wszystkie @ARGVpliki kończące się na „.gz” lub „.Z”:

while (<>) {
    print;
}

2
Myślę, że nie musisz uciekać |z wymiany.
Chris Lutz

Patrzę na to i nie wiem, jak to działa. W którym momencie jest zcat |analizowane jako polecenie przepuszczające?
Ether

1
@Ether => wykrywanie potoków jest funkcją dwóch argumentów otwartych, których operator diamentu używa podczas otwierania każdego pliku@ARGV
Eric Strom

40

Jedną z moich ulubionych funkcji w Perlu jest używanie ||operatora boolowskiego do wybierania między zestawem opcji.

 $x = $a || $b;

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

Oznacza to, że można napisać:

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

aby podjąć pierwszą prawdziwą wartość z $a, $bi $c, lub domyślna0 inaczej.

W Perlu 5.10 jest również //operator, który zwraca lewą stronę, jeśli jest zdefiniowana, lub prawą, jeśli jest inaczej. Następujące wybiera pierwszy określono wartość z $a, $b, $club 0inaczej:

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

Można ich również używać z ich krótkimi formularzami, które są bardzo przydatne przy podawaniu wartości domyślnych:

$ x || = 0; # Jeśli $ x było fałszem, teraz ma wartość 0.

$ x // = 0; # Jeśli $ x było niezdefiniowane, ma teraz wartość zero.

Cheerio,

Paweł


4
Jest to tak popularny idiom, że trudno go kwalifikować jako „ukrytą” cechę.
Michael Carman

3
szkoda, że ​​ładna drukarka myśli // to komentarz :)
John Ferguson

2
Pytanie, czy istnieje „funkcja użycia” do korzystania z tych nowych operatorów, czy też są one domyślnie włączone? Nadal opieram się na funkcjach Perla 5.10.
JJ

6
// jest tam domyślnie, nie są potrzebne żadne specjalne poprawki. Możesz również przenieść go do 5.8.x za pomocą poprawki dor ... zobacz katalog autorzy / id / H / HM / HMBRAND / na dowolnym serwerze lustrzanym CPAN. FreeBSD 6.x i nowsze wersje robią to za Ciebie w swoim pakiecie Perl.
dland

2
Kiedy || lub // jest połączone z do {}, możesz hermetyzować bardziej złożone przypisanie, np. $ x = $ a || wykonaj {my $ z; 3 lub 4 linie wyprowadzenia; $ z};
RET

39

Operatory ++ i jednoargumentowe - działają nie tylko na liczbach, ale także na łańcuchach.

my $_ = "a"
print -$_

wydruki -a

print ++$_

wydruki b

$_ = 'z'
print ++$_

drukuje aa


3
Cytując perlvara: „Operator automatycznego dekrementacji nie jest magiczny”. Więc --nie działa na strunach.
moritz

„aa” nie wydaje się być naturalnym elementem występującym po „z”. Spodziewałbym się kolejnej najwyższej wartości ascii, czyli „{”.
Ether

4
Nie pytaj programisty, co następuje po "z"; zapytaj człowieka. Ta funkcja doskonale nadaje się do numerowania elementów na długiej liście.
Barry Brown

17
Kiedy nowy w Perlu zaimplementowałem tę funkcję z dokładnym zachowaniem z do aa, pokazałem to współpracownikowi, który się zaśmiał i mnie i powiedział „pozwól, że ci coś pokażę”. Trochę się rozpłakałem, ale czegoś się nauczyłem.
Copas

2
@Ether - Jeśli chcesz, użyj liczb i automatycznie zamień je na ASCII z ord(). Lub napisz małą klasę i przeciąż operatorów, aby zrobić to za Ciebie.
Chris Lutz

36

Ponieważ Perl ma prawie wszystkie „ezoteryczne” części z innych list, powiem ci jedną rzecz, której Perl nie może:

Jedyną rzeczą, której Perl nie może zrobić, jest posiadanie w kodzie gołych dowolnych adresów URL, ponieważ //operator jest używany do wyrażeń regularnych.

Na wypadek, gdybyś nie wiedział, jakie funkcje oferuje Perl, oto wybrana lista być może nie do końca oczywistych wpisów:

Urządzenie Duffa - w Perlu

Przenośność i standardowość - prawdopodobnie jest więcej komputerów z Perlem niż z kompilatorem C.

Klasa manipulacji plikami / ścieżkami - File :: Find działa w jeszcze większej liczbie systemów operacyjnych niż .Net

Cytaty dla list i ciągów znaków rozdzielanych spacjami - Perl pozwala wybrać prawie dowolne cudzysłowy dla listy i ograniczników ciągów

Przestrzenie nazw z możliwością aliasów - Perl ma je poprzez przypisania globalne :

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

Inicjatory statyczne - Perl może uruchamiać kod w prawie każdej fazie kompilacji i tworzenia instancji obiektu, od BEGIN(analiza kodu) do CHECK(po przeanalizowaniu kodu) do import(przy imporcie modułu) do new(instancja obiektu) do DESTROY(zniszczenie obiektu) do END(wyjście programu)

Funkcje są obywatelami pierwszej klasy - tak jak w Perlu

Zakres blokowy i zamknięcie - Perl ma jedno i drugie

Wywoływanie metod i akcesorów pośrednio przez zmienną - Perl też to robi:

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

Definiowanie metod za pomocą kodu - Perl również na to pozwala :

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

Wszechstronna dokumentacja online - dokumentacja Perla jest dostępna online i prawdopodobnie również w Twoim systemie

Magiczne metody wywoływane za każdym razem, gdy wywołasz „nieistniejącą” funkcję - Perl implementuje ją w funkcji AUTOLOAD

Symboliczne odniesienia - radzimy trzymać się od nich z daleka. Zjedzą twoje dzieci. Ale oczywiście Perl pozwala ci ofiarować swoje dzieci żądnym krwi demonom.

Zamiana wartości w jednym wierszu - Perl umożliwia przypisanie listy

Możliwość zastąpienia nawet podstawowych funkcji własną funkcjonalnością

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

lub

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

unlink($_) for @ARGV

Jestem fanem dokumentacji Perla w porównaniu z innymi językami, ale nadal uważam, że w przypadku Regexes i referencji można by to bardzo zracjonalizować. np. najlepszym podkładem dla wyrażeń regularnych nie jest Perlre, ale Perlop
John Ferguson

9
„Jedyną rzeczą, której Perl nie może zrobić, jest posiadanie w kodzie gołych, dowolnych adresów URL, ponieważ operator // jest używany w wyrażeniach regularnych”. - to kompletny nonsens.

Dziękuję za wgląd. Przyjrzałem się kilku sposobom na uzyskanie czystego http: // ... adresu URL w kodzie Perla bez użycia filtru źródłowego i nie znalazłem sposobu. Może możesz pokazać, jak to jest możliwe? // jest używany do wyrażeń regularnych w wersjach Perla do 5.8.x.W wersji 5.10 jest zmieniony na zdefiniowane lub przypisanie.
Corion

8
Dlaczego / gdzie miałbyś chcieć odsłonić adresy URL w swoim kodzie? Nie mogę wymyślić żadnego przykładu.
rozbitek

18
Nikt by tego nie chciał, to tylko mem Java. „ foo.com ” to etykieta http:, a następnie „foo.com” w komentarzu. Niektórzy uważają to za interesujące, ponieważ ... są głupi.
jrockway

35

Autowifikacja . AFAIK nie ma go żaden inny język .


Nie miałem pojęcia, że ​​Python i inni tego nie obsługują.
skiphoppy

@davidnicol: Naprawdę? Czy możesz podać link? Moje szybkie wyszukiwanie w Google nic nie zwróciło. Dla tych, którzy nie znają ECMAscript to poprawna nazwa dla Javascript. en.wikipedia.org/wiki/ECMAScript
JJ

1
Jest też moduł do wyłączania autowikacji
Alexandr Ciornii

1
@Gregg Lind - Biorąc pod uwagę, że Python automatycznie tworzy zmienne za każdym razem, gdy po raz pierwszy je przypisujesz, autowifikacja spowodowałaby potworne problemy z jednej literówki.
Chris Lutz

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

31

W Perlu można łatwo zacytować prawie każdy dziwny ciąg znaków.

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

W rzeczywistości różne mechanizmy cytowania w Perlu są dość interesujące. Mechanizmy cytowania podobne do wyrażeń regularnych Perla pozwalają na cytowanie wszystkiego, z podaniem ograniczników. Możesz użyć prawie każdego znaku specjalnego, takiego jak #, /, lub znaków otwarcia / zamknięcia, takich jak (), [] lub {}. Przykłady:

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

Mechanizmy cytowania:

q: dosłowny cudzysłów; jedyną postacią, której trzeba zmienić, jest znak końcowy. qq: zinterpretowany cytat; przetwarza zmienne i znaki ucieczki. Świetne do ciągów, które musisz zacytować:

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

qx: Działa jak qq, ale następnie wykonuje je jako polecenie systemowe, nie interaktywnie. Zwraca cały tekst wygenerowany ze standardowego wyjścia. (Przekierowanie, jeśli jest obsługiwane w systemie operacyjnym, również pojawia się) Również wykonane z cudzysłowami wstecznymi (znak `).

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

qr: interpretuje jak qq, ale następnie kompiluje jako wyrażenie regularne. Działa również z różnymi opcjami wyrażenia regularnego. Możesz teraz przekazać wyrażenie regularne jako zmienną:

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: Bardzo, bardzo przydatny operator cytatów. Zamienia zestaw słów oddzielonych spacjami w cudzysłowy w listę. Doskonały do ​​wypełniania danych w teście jednostkowym.


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

Świetnie się z nich korzysta, gdy tylko wszystko staje się jaśniejsze. Dla qx, qq i q najprawdopodobniej używam operatorów {}. Najczęstszym nawykiem osób używających qw jest zwykle operator (), ale czasami pojawia się również qw //.


1
Czasami używam qw "", aby podświetlacze składni podświetliły go poprawnie.
Brad Gilbert,

Działa dla mnie w SlickEdit. :)
Robert P

1
@fengshaun, Redaktorzy, których zwykle używam , zaznaczają je poprawnie. Częściowo odnosiłem się do wyróżnienia składni w StackOverflow.
Brad Gilbert

@Brad Gilbert: Stack Overflow nie może (cóż, (nie) analizuje Perla wartego diddly squat. ☹
tchrist

my $moreout = qx{type "$path" 2>&1};... Nie wiedziałem, że możesz to zrobić! [TM]
dland

27

Niezupełnie ukryte, ale wielu programistów Perla na co dzień nie wie o CPAN . Dotyczy to szczególnie osób, które nie są programistami na pełny etat lub nie programują w pełnym wymiarze czasu w Perlu.


27

Instrukcja „for” może być używana w ten sam sposób, w jaki „with” jest używane w Pascalu:

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

Możesz zastosować sekwencję operacji s /// itp. Do tej samej zmiennej bez konieczności powtarzania nazwy zmiennej.

UWAGA: nierozdzielająca spacja powyżej (& nbsp;) ukryła w niej Unicode, aby obejść Markdown. Nie kopiuj, wklej go :)


A "map" też robi tę samą sztuczkę ... map {....} $ item; Jedną z zalet używania "dla" ponad "mapy" jest to, że możesz użyć następnego do wyrwania się.
draegtun

2
Ponadto w przypadku manipulowanego elementu jest wymieniony przed kodem wykonującym manipulację, co prowadzi do lepszej czytelności.
Robert P

@RobertP: Zgadza się. W dyskursie przydatny jest tematalizator.
tchrist

26

Operator słowa cudzysłowu to jedna z moich ulubionych rzeczy. Porównać:

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

i

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

Dużo mniej hałasu, przyjemniejszy dla oka. Kolejną bardzo fajną rzeczą w Perlu, której naprawdę brakuje podczas pisania SQL, jest to, że końcowy przecinek jest legalny:

print 1, 2, 3, ;

Wygląda to dziwnie, ale nie, jeśli w kodzie wciśniesz w inny sposób:

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

Dodanie dodatkowego argumentu do wywołania funkcji nie wymaga majstrowania przy przecinkach w poprzednich lub końcowych wierszach. Zmiana pojedynczej linii nie ma wpływu na otaczające ją linie.

Dzięki temu praca z różnymi funkcjami jest bardzo przyjemna. Jest to prawdopodobnie jedna z najbardziej niedocenianych funkcji Perla.


2
Ciekawym narożnym przypadkiem składni Perla jest to, że obowiązuje: dla $ _ qw (lista rzeczy) {...}
ephemient

1
Możesz nawet nadużywać składni glob przy cytowaniu słów, o ile nie używasz znaków specjalnych, takich jak * ?. Możesz więc pisaćfor (<a list of stuff>) { ... }
moritz,

1
@ephemient: prawie. To działa tylko z leksykalnymi: for my $ x qw (abc) {...} Na przykład: for $ _ qw (abc) {print} # nic nie drukuje
dland

po co dodawać ten dodatkowy słownik, skoro możesz cieszyć się ulubionym domyślnym językiem Perla? for (qw / abcd /) {print; }
fengshaun

2
@ephemient, @fengshaun, @moritz, @dland: To jest „naprawione” w blead ; zobacz ten wątek p5p .
tchrist

26

Możliwość analizowania danych bezpośrednio wklejanych do bloku DATA . Nie ma potrzeby zapisywania do pliku testowego, aby otworzyć go w programie lub podobnym. Na przykład:

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

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

I bardzo przydatne w małych testach!
fengshaun

@peter mortensen, jak miałbyś wiele bloków? A jak kończysz blok?
Ropuch

@Toad: to odpowiedź allana (zobacz listę wersji). Lepiej jest zwrócić się do tego użytkownika. Lub, skoro ten użytkownik opuścił Stack Overflow, może nie zwracać się do nikogo w szczególności (aby prawdziwy ekspert Perla mógł to później wyjaśnić).
Peter Mortensen

3
@Hai: Nie, to jest nie brzydka - w rzeczywistości jest dokładnie przeciwieństwem brzydki: to czyste, smukły, minimal, i piękne; jednym słowem, jest cudowny, a języki bez niego to PITA. @peter mortensen, @toad: Jedną z odpowiedzi na pytanie, jak mieć wiele bloków danych w tym samym programie, jest użycie modułu Inline :: Files poza CPAN.
tchrist

Inline :: Files jest implementowane przy użyciu filtrów źródłowych. Istnieje również Data :: Section, która zapewnia wiele bloków wbudowanych i nie używa filtrów źródłowych.
Prakash K

24

Nowe operacje blokowe

Powiedziałbym, że jedną z nich jest możliwość rozszerzenia języka, tworzenia pseudobloków.

  1. Deklarujesz prototyp dla sub, wskazując, że najpierw pobiera odwołanie do kodu:

    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. Możesz wtedy tak to nazwać w ciele

    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::Dumperto kolejny pół-ukryty klejnot.) Zwróć uwagę, że nie potrzebujesz subsłowa kluczowego przed blokiem ani przecinka przed hashem. Kończy się bardzo podobnie do:map { } @list

Filtry źródłowe

Istnieją również filtry źródłowe. Gdzie Perl przekaże Ci kod, abyś mógł nim manipulować. Zarówno to, jak i operacje blokowe, są w zasadzie rzeczy typu „nie próbuj tego w domu”.

Zrobiłem kilka fajnych rzeczy z filtrami źródłowymi, na przykład stworzyłem bardzo prosty język do sprawdzania czasu, zezwalając na krótkie jednowierszowe Perl do podejmowania decyzji:

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

Lib::TL po prostu przeszukałby zarówno „zmienne”, jak i stałe, utworzył je i zastąpił w razie potrzeby.

Ponownie, filtry źródłowe mogą być nieuporządkowane, ale są potężne. Ale mogą zepsuć debuggery coś strasznego - a nawet ostrzeżenia mogą być drukowane z niewłaściwymi numerami linii. Przestałem używać Switcha Damiana ponieważ debugger straciłby wszelkie możliwości powiedzenia mi, gdzie naprawdę jestem. Ale odkryłem, że możesz zminimalizować szkody, modyfikując małe fragmenty kodu, utrzymując je w tej samej linii.

Signal Hooks

Często się to robi, ale nie jest to wcale takie oczywiste. Oto osoba obsługująca kości, która wraca do starego.

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

Oznacza to, że za każdym razem, gdy jakiś inny moduł w kodzie chce umrzeć, musi do ciebie przyjść (chyba że ktoś inny dokona destrukcyjnego nadpisania $SIG{__DIE__} ). I możesz zostać powiadomiony, że ktoś coś zrobi z błędem.

Oczywiście w przypadku wystarczającej liczby rzeczy możesz po prostu użyć END { }bloku, jeśli wszystko, co chcesz zrobić, to posprzątać.

overload::constant

Możesz sprawdzić literały określonego typu w pakietach, które zawierają Twój moduł. Na przykład, jeśli używasz tego w swoim importsub:

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

będzie to oznaczać, że każda liczba całkowita większa niż 2 miliardy w wywoływanych pakietach zostanie zamieniona na Math::BigIntobiekt. (Zobacz overload :: constant ).

Zgrupowane literały całkowite

Skoro już przy tym jesteśmy. Perl pozwala ci podzielić duże liczby na grupy po trzy cyfry i nadal uzyskać z nich parsowalną liczbę całkowitą. Uwaga 2_000_000_000powyżej za 2 miliardy.


5
Używając programów obsługi $ SIG { DIE }, zdecydowanie zaleca się sprawdzenie $ ^ S w celu sprawdzenia, czy program faktycznie umiera, czy też po prostu wyrzuca wyjątek, który ma zostać przechwycony. Zwykle nie chcesz ingerować w to drugie.
pjf

Nowy blok jest bardzo pouczający! Myślałem, że to semantyczny język! Wielkie dzięki.
ZeroCool

Pouczającym zastosowaniem filtru źródłowego jest NiceSlice pdl ( pdl.perl.org/?docs=NiceSlice&title=PDL::NiceSlice ), dzięki czemu nie trzeba używać metody ->slicejako metody za każdym razem, gdy potrzebny jest plasterek.
Joel Berger

24

Binarny „x” jest operatorem powtórzenia :

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

Działa również z listami:

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

To jeden z powodów, dla których Perl jest tak popularny wśród hakerów. perl -e 'print 0x000 x 25';
JJ

4
Moim ulubionym zastosowaniem jest generowanie symboli zastępczych dla ostatniej części instrukcji SQL INSERT: @p = ('?') X $ n; $ p = dołącz (",", @p); $ sql = "WSTAW ... WARTOŚCI ($ p)";
skiphoppy

24

Sprawdzanie skazy. Po włączeniu sprawdzania skażeń perl umrze (lub ostrzeże, z-t ), jeśli spróbujesz przekazać skażone dane (z grubsza, dane spoza programu) do niebezpiecznej funkcji (otwarcie pliku, uruchomienie polecenia zewnętrznego itp.). Jest to bardzo pomocne przy pisaniu skryptów setuid lub CGI lub czegokolwiek, gdzie skrypt ma większe uprawnienia niż osoba przekazująca mu dane.

Magic goto. goto &subwykonuje zoptymalizowane wywołanie ogonowe.

Debugger.

use stricti use warnings. To może uchronić Cię przed wieloma literówkami.


1
Dlaczego inne języki nie mają tej funkcji? Ta funkcja sprawia, że ​​skrypty internetowe Perla są o rząd wielkości bezpieczniejsze.
Matthew Lock

22

Bazując na sposobie implementacji przełączników "-n"i "-p"w Perlu 5, możesz napisać pozornie niepoprawny program zawierający }{:

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

który jest wewnętrznie konwertowany na ten kod:

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

@martin clayton: Dlaczego tak się nazywa?
tchrist

@tchrist - bo podobno wygląda jak dwie osoby pocierające nosy. Z profilu, jeśli widzisz, co mam na myśli.
Martin Clayton

18

Zacznijmy łatwo od operatora statku kosmicznego .

$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 ++ nie zwraca 3 wartości dla liczb. Jeśli pamięć służy, funkcje porównywania ciągów są jedynymi 3 zwracanymi wartościami, które znam w całym języku STL. AFAIK Python nie ma 3 zwrotnych porównań liczbowych. W Javie nie ma również określonego dla liczby 3 zwracanego porównania.
JJ

7
Warto wspomnieć o tym, co jest tak przydatne w operatorach porównania -1/0/1, ponieważ nie każdy może wiedzieć: możesz połączyć je razem z operatorem lub, aby wykonać podstawowe / dodatkowe / itp. sortuje. Więc ($a->lname cmp $b->lname) || ($a->fname cmp $b->fname)sortuje ludzi według ich nazwisk, ale jeśli dwie osoby mają to samo nazwisko, zostaną uporządkowane według ich imienia.
Hobbs

@JJ Python ma porównanie 3 wartości: cmp () >>> print (cmp (5,7), cmp (6,6), cmp (7,5)) (-1, 0, 1)
bukzor

18

To jest meta-odpowiedź, ale archiwa Perl Tips zawierają różnego rodzaju interesujące sztuczki, które można wykonać za pomocą Perla. Archiwum wcześniejszych wskazówek jest dostępne w trybie on-line do przeglądania i można je subskrybować za pośrednictwem listy mailingowej lub kanału Atom.

Niektóre z moich ulubionych wskazówek obejmują budowanie plików wykonywalnych za pomocą PAR-a , używanie autodie do automatycznego generowania wyjątków oraz używanie konstrukcji przełącznika i inteligentnego dopasowania w Perlu 5.10.

Ujawnienie: Jestem jednym z autorów i opiekunów Perl Tips, więc oczywiście bardzo wysoko o nich myślę. ;)


2
Jest to prawdopodobnie jeden z najlepiej udokumentowanych języków, który jest wzorcem dla narzędzi do przeszukiwania dokumentacji. Że lista w tym pytaniu prawdopodobnie nie jest tak potrzebna jak w przypadku innych języków.
Axeman

1
autodie wygląda bardzo ładnie.
j_random_hacker,

18

map - nie tylko dlatego, że czyni swój kod bardziej wyrazistym, ale dlatego, że dała mi impuls do poczytania czegoś więcej o tym „programowaniu funkcjonalnym”.


15

Klauzula continue w pętlach. Zostanie wykonany na dole każdej pętli, nawet tych następnych.

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

Mój głos skierowałby się na grupy (? {}) I (?? {}) w wyrażeniach regularnych Perla. Pierwsza wykonuje kod Perla, ignorując zwracaną wartość, druga wykonuje kod, używając wartości zwracanej jako wyrażenia regularnego.


Perl wynalazł tak wiele rozszerzeń wyrażeń regularnych, że inne programy obecnie często używają wyrażenia regularnego pcre (zgodne z Perlem) zamiast oryginalnego języka wyrażeń regularnych.
Sek.

Przeczytaj małą notkę tutaj perldoc.perl.org/… :-D
JJ,

Perl naprawdę (o ile wiem) prowadzi paczkę, jeśli chodzi o wyrażenia regularne.
Brad Gilbert

O ile mi wiadomo, jest to wciąż eksperymentalne i może nie działać tak samo w przyszłych Perls. Nie znaczy to, że nie jest to przydatne, ale nieco bezpieczniejszą i równie użyteczną wersję można znaleźć w fladze / e polecenia s ///: s/(pattern)/reverse($1);/ge;# odwraca wszystko patterns.
Chris Lutz,

@Chris Lutz, @Leon Timmerman: Zauważ, że te dwie konstrukcje są teraz ponownie przenoszone. Zwróć również uwagę, że drugi nie musi już być używany do wpływania na wzorce rekurencyjne, ponieważ teraz możemy powtarzać na grupach przechwytywania. @Brad Gilbert: Zgadza się, chociaż PCRE dobrze nas śledzi; jedną z dziedzin doskonałości wyrażeń regularnych, w której Perl nie ma żadnych wyzwań, jest dostęp do właściwości Unicode; zobacz moje unitrio dystrybucję uninames, unicharsa zwłaszcza uniprops, aby zobaczyć tylko część tego, co mam na myśli.
tchrist

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

kotwica \ G. Jest gorąco .


3
... i wskazuje miejsce zakończenia poprzedniego meczu.
Dave Sherohman

1
Ale musisz wywołać swoje wyrażenie regularne w kontekście skalarnym.
davidnicol

@davidnicol: Powyższy kod działa. Czy możesz wyjaśnić, co masz na myśli?
JJ

13

m//Operator ma jakieś niejasne przypadki szczególne:

  • Jeśli używasz ?jako separatora, pasuje on tylko raz, chyba że zadzwonisz reset.
  • Jeśli używasz 'jako separatora, wzór nie jest interpolowany.
  • Jeśli wzorzec jest pusty, używa wzorca z ostatniego udanego dopasowania.

2
To bardziej przypomina ukryte pułapki niż ukryte funkcje! Nie znam nikogo, kto je lubi. Wątek na p5p jakiś czas temu omawiał użyteczność domniemanej flagi m / $ foo / r, gdzie / r oznaczałoby brak interpolacji (litera nie jest ważna), ponieważ nikt nigdy nie pamięta pojedynczej cudzysłowu.
dland

2
@dland: Zgoda; Nazwałbym te ukryte błędne funkcje i nigdy nie użyłbym ich w kodzie produkcyjnym.
Michael Carman,

7
Nie mogę sobie wyobrazić programisty Perla, który nie byłby w stanie zapamiętać (lub nawet zgadywać), że pojedyncze cudzysłowy oznaczają brak interpolacji. Jego użycie z tą semantyką jest prawie uniwersalne w języku, którego raczej bym się spodziewał ...
sundar - Przywróć Monikę

a jeśli wzorzec jest pusty, a ostatnie udane dopasowanie zostało skompilowane z modyfikatorem / o, od tego momentu będzie utknęło na tym wzorcu.
davidnicol

1
Myślę, że zachowanie pustego wzorca zostało wycofane. Przede wszystkim dlatego, że wzorzec taki jak m / $ foo / staje się paskudnym błędem, gdy $ foo jest puste.
Matthew S

12

Operator diamentu uchwytu pliku o wartości null <> ma swoje miejsce w tworzeniu narzędzi wiersza poleceń. Działa jak <FH>czytanie z uchwytu, z tym wyjątkiem, że w magiczny sposób wybiera to, co zostanie znalezione jako pierwsze: nazwy plików w wierszu poleceń lub STDIN. Zaczerpnięte z Perlop:

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

4
Jest to również zgodne z semantyką UNIX-ową, polegającą na używaniu "-" w znaczeniu "odczytu ze standardowego wejścia. Więc możesz to zrobić perl myscript.pl file1.txt - file2.txt, a perl przetworzy pierwszy plik, potem stdin, a potem drugi plik.
Ryan C. Thompson

Można operator na własnych obiektach ( ) do pracy jak iteratora. Jednak nie działa to, czego można się spodziewać w kontekście listy. overload<><$var>
dolmen

11

Specjalne bloki kodu , takich jak BEGIN, CHECKi END. Pochodzą z Awk, ale działają inaczej w Perlu, ponieważ nie jest oparty na rekordach.

BEGINBlok może być użyta do określenia kodu dla fazy analizowania; jest również wykonywana podczas sprawdzania składni i zmiennych perl -c. Na przykład, aby załadować zmienne konfiguracyjne:

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

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

zmienia nazwę data.txt.part na data.txt bez konieczności powtarzania tego.


10

Nieco niejasny jest "operator" tylda-tylda, który wymusza kontekst skalarny.

print ~~ localtime;

jest taki sam jak

print scalar localtime;

i inny niż

print localtime;

5
Jest to szczególnie niejasne, ponieważ perl5.10.0 wprowadza także „inteligentny operator dopasowania” ~~, który może dokonywać dopasowań wyrażeń regularnych, może sprawdzać, czy element znajduje się w tablicy i tak dalej.
moritz

To nie jest niejasne, jest zaciemnione (i przydatne w golfie i JAPH).
Michael Carman

To nie jest poprawne! ~~ nie jest bezpieczne w przypadku odniesień! To je ciągnie.
Leon Timmermans

No tak. Stringifikacja jest tym, co dzieje się z odwołaniami, gdy są wymuszane w kontekście skalarnym. Jak to sprawia, że ​​„~~ wymusza kontekst skalarny” jest niepoprawne?
Dave Sherohman

3
@Nomad Dervish: kontekst skalarny / = stringification. np. „$ n = @a” jest kontekstem skalarnym. „$ s = qq '@ a'” to ciągifikacja. W odniesieniu do odniesień „$ ref1 = $ ref2” jest kontekstem skalarnym, ale nie jest określane jako łańcuch.
Michael Carman


9

„Tryb desperacji” konstrukcji sterujących pętli Perla, który powoduje, że przeszukują stos w celu znalezienia pasującej etykiety, pozwala na kilka ciekawych zachowań, które Test :: More wykorzystuje, na lepsze lub gorsze.

SKIP: {
    skip() if $something;

    print "Never printed";
}

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

Jest mało znany plik .pmc. „użyj Foo” będzie szukał Foo.pmc w @INC przed Foo.pm. Miało to na celu umożliwienie pierwszego załadowania skompilowanego kodu bajtowego, ale Module :: Compile wykorzystuje to do buforowania modułów filtrowanych według źródła w celu skrócenia czasu ładowania i łatwiejszego debugowania.

Możliwość zmiany ostrzeżeń w błędy.

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

To jest to, co przychodzi mi do głowy z głowy, o czym nie wspomniałem.


9

Operator kóz *:

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

lub

sub foo {
    return @_;
}

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

Działa, ponieważ przypisanie listy w kontekście skalarnym daje liczbę elementów na przypisanej liście.

* Uwaga, nie jest to operator


To najpiękniejszy (no przynajmniej) najpiękniejszy „operator” w historii.
Chris Lutz
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.