Perl gizli özellikleri?


143

Yararlı işler yapmak için kullanabileceğiniz gerçekten yararlı ama ezoterik dil özellikleri nelerdir?

Kuralları:

  • Yanıtları CPAN'a değil Perl çekirdeğine sınırlamaya çalışın
  • Lütfen bir örnek ve kısa bir açıklama verin

Gizli Özellikler Diğer dillerde de bulunmaktadır Gizli Özellikler:

(Bunların hepsi Corion'un cevabından )

  • C
    • Duff'ın Cihazı
    • Taşınabilirlik ve Standartlık
  • C #
    • Boşlukla sınırlandırılmış listeler ve dizeler için alıntılar
    • Takma ad alanları
  • Java
    • Statik Başlatıcılar
  • JavaScript
    • İşlevler Birinci Sınıf vatandaşlar
    • Blok kapsamı ve kapatma
    • Bir değişken üzerinden dolaylı olarak çağrı yöntemleri ve erişimcileri
  • yakut
    • Kod ile yöntem tanımlama
  • PHP
    • Yaygın çevrimiçi belgeler
    • Büyü yöntemleri
    • Sembolik referanslar
  • piton
    • Bir satır değer değişimi
    • Çekirdek işlevleri bile kendi işlevlerinizle değiştirebilme

Diğer Gizli Özellikler:

Operatörler:

Alıntı yapıları:

Sözdizimi ve İsimler:

Modüller, Pragmas ve komut satırı seçenekleri:

Değişkenler:

Döngüler ve akış kontrolü:

Düzenli ifadeler:

Diğer özellikler:

Diğer püf noktaları ve meta-cevaplar:


Ayrıca bakınız:


Bu özelliklerin çoğu günlük kullanımdadır, bazıları Perl betiklerinin çoğunda görülür ve çoğu "Diğer" altında listelenen diğer dillerden kaynaklanır ve bu "gizli" olarak adlandırılması sorunun amacını değiştirir.
reinierpost

Yanıtlar:


54

Flip-flop operatörü, bir bayrak tutamacı kullanmadan bir dosya tanıtıcısı tarafından döndürülen kayıtlar (genellikle satırlar) arasında geçiş yaparken ilk yinelemeyi atlamak için kullanışlıdır:

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

perldoc perlopDaha fazla bilgi ve örnek için "flip-flop" komutunu çalıştırın .


Aslında bu, Pattern1, pattern2 yazarak iki desen arasında flip-flop yapabileceğiniz Awk'tan alınmıştır
Bruno De Fraine

15
Açıklığa kavuşturmak gerekirse, bunun "gizli" yönü, eğer herhangi bir skaler '..' için işlenen bir sabit ise, değerin dolaylı olarak giriş satırı numarası ($.)
İle karşılaştırılmasıdır

47

Perl'de belirgin olmayan birçok özellik var.

Örneğin, bir sigilden sonra bir boşluk olabileceğini biliyor muydunuz?

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

Yoksa sembolik referanslar kullanırsanız alt sayısal adlar verebilir misiniz?

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

Gerçek ifadeler için 1 ve false için boş dize döndüren "bool" yarı operatörü de vardır:

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

Diğer ilginç şeyler: ile use overload sizinle dize değişmezlerini ve sayılarını aşırı yükleyebilirsiniz (ve örneğin onları BigInts veya her neyse yapabilirsiniz).

Bunların çoğu aslında bir yerde belgelenir veya belgelenmiş özelliklerden mantıklı bir şekilde izlenir, ancak yine de bazıları çok iyi bilinmemektedir.

Güncelleme : Güzel bir tane daha. Aşağıda q{...}alıntı yapılar bahsedildi, ama sen sınırlayıcı olarak harfleri kullanabilirsiniz biliyor muydunuz?

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

Aynı şekilde düzenli ifadeler de yazabilirsiniz:

m xabcx
# same as m/abc/

2
“Sigilden sonra boşluk olabileceğini biliyor muydun?” Ben tamamen şaşırmışım. Vay.
Aristoteles Pagaltzis

1
Güzel! !! $ undef_var bir uyarı oluşturmuyor.
Axeman

4
Ben dizeleri sınırlamak için harf kullanma örneği "Jet another perl hacker" yerine " Sadece başka bir perl hacker" olması gerektiğini düşünüyorum = P
Chris Lutz

En kötü yanı, başka şeyleri de sınırlayıcı olarak kullanabilmenizdir. Hatta kapanış destekleri. Aşağıdakiler geçerlidir: s} regex} replacement} xsmg; q] dizgi değişmezi];
Ryan

46

Sihirli ARGV ile sıkıştırılmış dosyalar için destek ekleyin :

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;

(içinde kabuk metakarakterleri olan dosya adlarını işlemek için $ _ civarında alıntı yapmak gerekir)

Şimdi bu <>özellik @ARGV".gz" veya ".Z" ile biten dosyaları açar.

while (<>) {
    print;
}

2
Ben |yedek yerine kaçmak gerektiğini sanmıyorum .
Chris Lutz

Buna bakıyorum ve nasıl çalıştığını anlayamıyorum. Hangi noktada zcat |geçecek bir komut olarak ayrıştırılır?
Eter

1
@Ether => boruları tespit etmek, elmas operatörünün her dosyayı açarken kullandığı iki argümanın açık bir özelliğidir@ARGV
Eric Strom

40

Perl'deki en sevdiğim özelliklerden biri, ||bir dizi seçenek arasında seçim yapmak için boolean operatörünü kullanmak .

 $x = $a || $b;

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

Bu, kişinin yazabileceği anlamına gelir:

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

ilk gerçek değerini almak $a, $bve $c, veya varsayılan bir bölgesinin0 aksi.

Perl 5.10'da //tanımlanmışsa sol tarafı, aksi takdirde sağ tarafı döndüren operatör de vardır . Aşağıdaki seçer önce tanımlandığı değerden $a, $b, $cya da 0başka şekilde:

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

Bunlar, varsayılanları sağlamak için çok yararlı olan kısa el formlarıyla da kullanılabilir:

$ x || = 0; # $ X yanlışsa, şimdi 0 değerine sahiptir.

$ x // = 0; # $ X tanımsızsa, şimdi sıfır değerine sahiptir.

Görüşürüz

Paul


4
Bu çok yaygın bir deyimdir ve "gizli" bir özellik olarak nitelendirilemez.
Michael Carman

3
utanç güzel yazıcı düşünüyor // bir yorum :)
John Ferguson

2
Soru, bu yeni operatörleri kullanmak için bir "kullanım özelliği" var mı yoksa varsayılan olarak etkin mi? Hala Perl 5.10'un özelliklerini eğiyorum.
JJ

6
// varsayılan olarak oradadır, özel bir ayarlamaya gerek yoktur. Ayrıca dor-patch ile 5.8.x içine backport ... herhangi bir CPAN ayna üzerinde yazar / id / H / HM / HMBRAND / dizini bakın. FreeBSD 6.x ve ötesi bunu perl paketlerinde sizin için yapar.
dland

2
Ne zaman || veya // do {} ile birleştirildiğinde, daha karmaşık bir ödevi kapsül içine alabilirsiniz, yani $ x = $ a || {{$ $; 3 veya 4 tür türev; $ z};
RET

39

++ ve unary işleçleri - yalnızca sayılar üzerinde değil, dizelerde de çalışır.

my $_ = "a"
print -$_

baskılar -a

print ++$_

baskılar b

$_ = 'z'
print ++$_

baskılar aa


3
Perlvar alıntılamak için: "Otomatik azaltma operatörü büyülü değil." Dize üzerinde --çalışmaz.
moritz

"aa", "z" yi izleyen doğal bir öğe gibi görünmemektedir. Bir sonraki en yüksek ascii değerini beklerdim, "{".
Eter

4
Bir programcıya "z" den sonra ne olduğunu sormayın; bir insana sor. Bu özellik, uzun bir listedeki öğeleri numaralandırmak için mükemmeldir.
Barry Brown

17
Perl için yeni olduğunda, bu özelliği kendime bir davranışa z ile uyguladım ve sonra güldü ve bana bir iş arkadaşı göstereyim dedi. Biraz ağladım ama bir şeyler öğrendim.
Copas

2
@Ether - İsterseniz, sayıları kullanın ve ile ASCII'ye otomatik dönüştürün ord(). Ya da, küçük bir sınıf yazın ve sizin için yapacak operatörleri aşırı yükleyin.
Chris Lutz

36

Perl diğer listelerden neredeyse tüm "ezoterik" parçalara sahip olduğundan, size Perl'in yapamayacağı tek şeyi söyleyeceğim:

Perl'in yapamayacağı tek şey, kodunuzda çıplak keyfi URL'lere sahip olmaktır, çünkü //Operatör normal ifadeler için kullanıldığından .

Perl'in hangi özellikleri sunduğunun size açık olmaması durumunda, belki de tamamen açık olmayan girişlerin seçici bir listesi:

Duff'ın Cihazı - Perl'de

Taşınabilirlik ve Standartlık - Perl'li bir C derleyicisinden daha fazla bilgisayar olması muhtemeldir

Bir dosya / yol manipülasyon sınıfı - Dosya :: Bul, .Net'ten daha fazla işletim sisteminde çalışır

Boşlukla ayrılmış listeler ve dizeler için alıntılar - Perl, listeniz ve dize sınırlayıcıları için neredeyse keyfi tırnaklar seçmenize olanak tanır

Takma ad alanları - Perl, glob atamalarıyla bunlara sahiptir:

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

Statik başlatıcılar - Perl, derlemeyi ve nesne somutlaştırmanın hemen hemen her aşamasında kodu çalıştırabilir BEGIN(kod ayrıştırması) (kod ayrıştırmasından CHECKsonra) import(modül içe aktarımında) ile new(nesne somutlaması) - DESTROY(nesne imhası) - END(program çıkışı)

İşlevler Birinci Sınıf vatandaşlardır - tıpkı Perl'de olduğu gibi

Blok kapsamı ve kapatma - Perl,

Bir değişken aracılığıyla dolaylı olarak çağrı yöntemleri ve erişimcileri - Perl de bunu yapar:

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

Yöntemleri kodla tanımlama - Perl de şunları sağlar :

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

Yaygın çevrimiçi belgeler - Perl belgeleri çevrimiçi ve muhtemelen sisteminizde

"Varolmayan" bir işlev çağırdığınızda çağrılan sihirli yöntemler - Perl, AUTOLOAD işlevinde bunu uygular

Sembolik referanslar - bunlardan uzak durmanız önerilir. Çocuklarını yiyecekler. Ama elbette, Perl çocuklarınıza kana susamış şeytanları sunmanıza izin veriyor.

Bir satır değerinin değiştirilmesi - Perl, liste atamasına izin verir

Çekirdek işlevleri bile kendi işlevlerinizle değiştirebilme

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

veya

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

unlink($_) for @ARGV

Ben diğer dillerle karşılaştırıldığında Perl'in belgelerinin hayranıyım, ama hala Regexes ve referanslar için çok rasyonelleştirilebileceğini düşünüyorum. regexes için en iyi astar Perlre değil, Perlop
John Ferguson

9
"Perl'in yapamayacağı tek şey, kodunuzda çıplak rastgele URL'lerin bulunmasıdır, çünkü // operatörü normal ifadeler için kullanılır." - bu tamamen saçmalık.

Fikriniz için teşekkürler. Kaynak filtresi kullanmadan Perl kodunda çıplak bir http: // ... URL'sine sahip olmanın bazı yollarına baktım ve bir yol bulamadım.Belki bunun nasıl mümkün olduğunu gösterebilirsiniz? // Perl sürümlerinde 5.8.x'e kadar düzenli ifadeler için kullanılır. 5.10'da tanımlı veya atama için yeniden kullanılır.
Corion

8
Kodunuzda neden / nerede çıplak URL'ler olmasını istersiniz ? Bir örnek düşünemiyorum.
castaway

18
Kimse istemez, bu sadece bir Java mem. " foo.com ", bir yorumda http: ve ardından "foo.com" etiketidir. Bazı insanlar bunu ilginç buluyor çünkü ... aptallar.
19'da jrockway

35

Otovivifikasyon . AFAIK başka hiçbir dile sahip değildir .


Python ve arkadaşlarının bunu desteklemediğine dair hiçbir fikrim yoktu.
skiphoppy

@davidnicol: Gerçekten mi? Bir bağlantı sağlayabilir misiniz? Google'da hızlı aramam hiçbir şey döndürmedi. ECMAscript bilmeyenler için Javascript için doğru isimdir. en.wikipedia.org/wiki/ECMAScript
JJ

1
Ve otovivikasyonu devre dışı bırakmak için bir modül var
Alexandr Ciornii 29.09.2010

1
@Gregg Lind - Python'un onlara her atadığınızda otomatik olarak değişkenler yarattığı düşünüldüğünde, otomatik canlılaştırma tek bir yazım hatasıyla korkunç sorunlar yaratacaktır.
Chris Lutz

3
@tchrist - a = [[x * y xrange için y (1,11)] x in xrange için (1,11)]
Şeye Giden

31

Perl'de hemen hemen her türlü tuhaf dizeyi alıntılamak basittir.

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

Aslında, Perl'deki çeşitli alıntı mekanizmaları oldukça ilginçtir. Perl regex benzeri alıntı mekanizmaları, sınırlayıcıları belirterek herhangi bir şey teklif etmenizi sağlar. #, / Gibi hemen hemen tüm özel karakterleri veya (), [] veya {} gibi açık / kapalı karakterleri kullanabilirsiniz. Örnekler:

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

Alıntılama mekanizmaları:

q: gerçek fiyat teklifi; sadece kaçması gereken karakter son karakterdir. qq: yorumlanmış bir alıntı; değişkenleri ve çıkış karakterlerini işler. Alıntı yapmanız gereken dizeler için harika:

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

qx: qq gibi çalışır, ancak daha sonra etkileşimli olmayan bir sistem komutu olarak yürütür. Standart çıkıştan oluşturulan tüm metni döndürür. (İşletim sisteminde destekleniyorsa yönlendirme de çıkar) Arka tırnak işaretleri (`karakteri) ile de yapılır.

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

qr: qq gibi yorumlar, ancak daha sonra bunu normal bir ifade olarak derler. Normal ifadedeki çeşitli seçeneklerle de çalışır. Artık normal ifadeyi değişken olarak iletebilirsiniz:

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: Çok, çok kullanışlı bir teklif operatörü. Alıntılanan boşlukla ayrılmış sözcük grubunu bir listeye dönüştürür. Birim testindeki verileri doldurmak için idealdir.


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

Her şeyi daha net hale getirdiğinde onları kullanmak harika. Qx, qq ve q için büyük olasılıkla {} operatörlerini kullanıyorum. Qw kullanan kişilerin en yaygın alışkanlığı genellikle () operatörüdür, ancak bazen qw // da görürsünüz.


1
Sözdizimi vurgulayıcıların doğru şekilde vurgulaması için bazen qw "" kullanıyorum.
Brad Gilbert

SlickEdit'te benim için çalışıyor. :)
Robert P

1
@fengshaun, editörler genellikle kullanmak do doğru bunlar vurgulayın. Kısmen StackOverflow'daki sözdizimi vurgulayıcıya atıfta bulunuyordum.
Brad Gilbert

@Brad Gilbert: Yığın Taşması Perl'i cesurca çömelmeye değmez (iyi değil). ☹
tchrist

my $moreout = qx{type "$path" 2>&1};... yapabileceğini bilmiyordum! [TM]
dland

27

Gerçekten gizli değil, ama her gün birçok Perl programcısı CPAN'ı bilmiyor . Bu özellikle tam zamanlı programcı olmayan veya Perl'de tam zamanlı program yapmayan kişiler için geçerlidir.


27

Pascal için "for" ifadesi "with" ile aynı şekilde kullanılabilir:

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

Değişken adını tekrarlamak zorunda kalmadan aynı değişkene bir dizi s / // işlemi vb. Uygulayabilirsiniz.

NOT: yukarıdaki kırılmayan alan (& nbsp;), Markdown'u atlatmak için içinde Unicode'u gizlemiştir. Yapıştır kopyalamayın :)


"Map" de aynı numarayı yapıyor ... map {....} $ item; "Üzerinden" harita "için" kullanmanın bir avantajı, daha sonra çıkmak için kullanabileceğinizdir.
draegtun

2
Ayrıca, manipüle edilen koddan önce öğenin manipüle edilmesini sağlayarak daha iyi okunabilirliğe yol açar.
Robert P

@RobertP: Bu oldukça doğru. Topikalleştirici söylemde faydalıdır.
tchrist

26

Queword operatörü benim en sevdiğim şeylerden biri. Karşılaştırmak:

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

ve

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

Çok daha az gürültü, göze daha kolay. Perl ile ilgili bir başka güzel şey, SQL yazarken gerçekten kaçırdığı bir nokta, bir virgülün yasal olmasıdır:

print 1, 2, 3, ;

Bu tuhaf görünüyor, ancak kodu başka bir şekilde girintilerseniz:

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

İşlev çağrısına ek bir bağımsız değişken eklemek, önceki veya sondaki satırlardaki virgüllerle uğraşmanızı gerektirmez. Tek hatlı değişimin çevresindeki hatlar üzerinde hiçbir etkisi yoktur.

Bu, varyasyon fonksiyonlarıyla çalışmayı çok keyifli hale getirir. Bu belki de Perl'in en düşük puan alan özelliklerinden biridir.


2
Perl'in sözdiziminin ilginç bir köşe örneği, aşağıdakilerin geçerli
olduğudur

1
*? Gibi özel karakterler kullanmadığınız sürece glob sözdizimini sözcük alıntılamak için kötüye kullanabilirsiniz. Böylece yazabilirsinizfor (<a list of stuff>) { ... }
moritz

1
@ephemient: neredeyse. Bu sadece sözlüklerle çalışır: $ x qw (abc) için {...} Örneğin: $ _ qw (abc) için {print} # hiçbir şey yazdırmaz
dland

perl'in favori varsayılanının tadını çıkarabildiğinizde neden bu ekstra sözcükleri eklemelisiniz? için (qw / abcd /) {print; }
fengshaun

2
@ephemient, @fengshaun, @moritz, @dland: en “sabit” Bu blead ; bkz bu P5P konu .
tchrist

26

Doğrudan bir VERİ bloğuna yapıştırılan verileri ayrıştırma yeteneği . Programda veya benzeri bir programda açılabilmesi için bir test dosyasına kaydetmeye gerek yoktur. Örneğin:

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

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

Ve küçük testlerde çok kullanışlı!
Haziran'da fengshaun

@peter mortensen nasıl birden fazla bloğunuz olur? Ve bir bloğu nasıl bitirirsiniz?
Kurbağa

@Toad: allan'ın cevabı (revizyon listesine bakınız). Bu kullanıcıya hitap etmek daha iyidir. Veya, bu kullanıcı Yığın Taşması'ndan ayrıldığından, belki de hiç kimseye hitap etmeyebilir (böylece gerçek bir Perl uzmanı daha sonra düzeltebilir).
Peter Mortensen

3
@Hai: Hayır, çirkin değil - aslında, çirkinin tam tersi: temiz, ince, minimal ve güzel; tek kelimeyle, harika ve onsuz diller bir PITA. @peter mortensen, @toad: Aynı programda birden çok veri bloğuna sahip olmanın bir cevabı Inline :: Files modülünü CPAN dışında kullanmaktır.
tchrist

Inline :: Dosyalar kaynak filtreleri kullanılarak uygulanır. Ayrıca , birden çok satır içi blok sağlayan ve kaynak filtreleri kullanmayan Data :: Bölümü de vardır .
Prakash K

24

Yeni Blok İşlemleri

Ben sözde blok işlemleri oluşturmak, dili genişletmek için yeteneği olduğunu söyleyebilirim.

  1. Önce bir kod başvurusu aldığını belirten bir alt için prototip bildirirsiniz:

    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. Daha sonra bunu vücutta şöyle diyebilirsiniz

    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::Dumperbaşka bir yarı gizli mücevherdir.) subBlok önünde anahtar kelimeye veya karma öncesi virgüllere nasıl ihtiyacınız olmadığına dikkat edin . Sonunda şuna benzer:map { } @list

Kaynak Filtreleri

Ayrıca, kaynak filtreleri de vardır. Perl'in kodu geçebileceği yer, böylece onu değiştirebilirsiniz. Hem bu hem de blok işlemleri, hemen hemen bunu evde denemeyin.

Kaynak filtreleri ile bazı düzgün şeyler yaptım, örneğin zamanı kontrol etmek için çok basit bir dil oluşturmak, bazı kararlar için kısa Perl tek satırlarına izin vermek gibi:

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

Lib::TL hem "değişkenleri" hem de sabitleri tarar, onları oluşturur ve gerektiğinde değiştirir.

Yine, kaynak filtreleri dağınık olabilir, ancak güçlüdür. Ancak hata ayıklayıcılara korkunç bir şey dağıtabilirler - hatta uyarılar yanlış satır numaralarıyla yazdırılabilir. Damian'ın kullanmayı bıraktım Switch'i çünkü hata ayıklayıcı bana nerede olduğumu söyleme yeteneğini kaybedecekti. Ancak, kodun küçük bölümlerini değiştirerek ve bunları aynı satırda tutarak hasarı en aza indirebileceğinizi öğrendim.

Sinyal Kancaları

Genellikle yeterlidir, ama o kadar da açık değildir. İşte domuzcuk eskisine dayanan bir kalıp işleyicisi.

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

Bu, koddaki başka bir modülün ölmek istediği zaman size gelmeleri gerektiği anlamına gelir (başka biri üzerine yıkıcı bir yazma yapmazsa) $SIG{__DIE__} ). Ve birilerinin bir şeylerin bir hata olduğu konusunda bilgilendirilebilirsiniz.

Tabii ki, tek yapmanız gereken sadece bir END { }blok kullanabilirsiniz , eğer tek yapmanız gereken temizlemek.

overload::constant

Modülünüzü içeren paketlerdeki belirli türdeki değişmez değerleri denetleyebilirsiniz. Örneğin, bunu importalt öğenizde kullanırsanız:

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

çağrı paketlerindeki 2 milyardan büyük her tamsayının bir Math::BigIntnesneye dönüşeceği anlamına gelir . (Bkz. Aşırı yük :: sabit ).

Gruplanmış Tam Sayı Değişmezleri

Biz varken. Perl, büyük sayıları üç basamaklı gruplara ayırmanıza ve yine de ondan ayrıştırılabilir bir tamsayı almanıza izin verir. 2_000_000_000Yukarıdaki not 2 milyar.


5
$ SIG { DIE } işleyicilerini kullanırken, programınızın gerçekten ölüp ölmediğini görmek için $ ^ S'yi incelemeniz ya da sadece yakalanacak bir istisna atmanız önemle tavsiye edilir. Genellikle ikincisine müdahale etmek istemezsiniz.
pjf

Yeni blok çok öğretici! Bence bir dil anlambilimiydi! çok teşekkürler.
ZeroCool

Kaynak filtrenin öğretici bir kullanımı pdl's NiceSlice'dır ( pdl.perl.org/?docs=NiceSlice&title=PDL::NiceSlice ), böylece ->sliceher dilim gerektiğinde bir yöntem olarak kullanılması gerekmez.
Joel Berger

24

İkili "x" yineleme operatörüdür :

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

Ayrıca listelerle çalışır:

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

Perl'in bilgisayar korsanları arasında bu kadar popüler olmasının bir nedeni de budur. perl -e 'baskı 0x000 x 25';
JJ

4
Bunun en sevdiğim kullanımı SQL INSERT deyiminin son kısmı için yer tutucu oluşturmaktır: @p = ('?') X $ n; $ p = join (",", @p); $ sql = "INSERT ... DEĞERLERİ ($ p)";
skiphoppy

24

Bozukluk kontrolü. Boya kontrolü etkinken, perl ölür (veya-t renkli verileri (kabaca konuşursak, programın dışından gelen veriler) güvenli olmayan bir işleve (bir dosyayı açma, harici komut çalıştırma, vb.) Aktarmaya çalışırsanız ). Setuid komut dosyaları veya CGI'lar veya komut dosyasının veri besleyen kişiden daha büyük ayrıcalıklara sahip olduğu herhangi bir şey yazarken çok yararlıdır.

Sihirli gitti. goto &suboptimize kuyruk çağrısı yapar.

Hata ayıklayıcı.

use strictve use warnings. Bunlar sizi bir sürü yazım hatalarından kurtarabilir.


1
Neden diğer dillerde bu özellik yok? Kullanılan bu özellik perl web betiklerini daha büyük bir sıraya göre daha güvenli hale getirir.
Matthew Lock

22

"-n"Ve "-p"anahtarlarının Perl 5'te uygulanma şekline bağlı olarak, aşağıdakiler de dahil olmak üzere yanlış görünen bir program yazabilirsiniz }{:

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

dahili olarak bu koda dönüştürülür:

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

@martin clayton: Buna neden deniyor?
tchrist

@tchrist - çünkü, sözde, iki kişi burun sürtünme gibi görünüyor. Profilde, ne demek istediğimi görürsen.
martin clayton

18

Uzay Gemisi Operatörü ile kolay başlayalım .

$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 ++ sayılar için 3 değer döndürmez. Eğer bellek Dize komapre fonksiyonları sunuyorsa tüm STL dilinde bildiğim tek 3 değer döndürür. AFAIK Python'un 3 dönüşlü sayısal karşılaştırması yoktur. Java'nın sayıya özgü 3 dönüş karşılaştırması da yoktur.
JJ

7
-1/0/1 karşılaştırma operatörleri hakkında neyin yararlı olduğunu belirtmek gerekir, çünkü herkes bilmeyebilir: birincil / ikincil / vb. Yapmak için onları or-operatörü ile birlikte zincirleyebilirsiniz. sıralar. Bu yüzden ($a->lname cmp $b->lname) || ($a->fname cmp $b->fname)insanları soyadlarına göre sıralar, ancak iki kişi aynı soyadına sahipse, ilk adlarına göre sıralanırlar.
Ocaklar

@JJ Python'un 3 değerli bir karşılaştırması var: cmp () >>> print (cmp (5,7), cmp (6,6), cmp (7,5)) (-1, 0, 1)
bukzor

18

Bu bir meta cevaptır, ancak Perl İpuçları arşivleri Perl ile yapılabilecek her türlü ilginç numara içerir. Önceki ipuçlarının arşivi, tarama için çevrimiçi durumdadır ve e-posta listesi veya atom beslemesi ile abone olabilirsiniz.

En sevdiğim ipuçlarından bazıları , PAR ile yürütülebilir dosyalar oluşturmak , istisnaları otomatik olarak atmak için autodie kullanmak ve Perl 5.10'da anahtar ve akıllı eşleştirme yapılarının kullanımını içerir .

Açıklama: Perl Tips'in yazarlarından ve koruyucularından biriyim, bu yüzden açıkça çok düşünüyorum. ;)


2
Muhtemelen orada en iyi belgelenmiş dillerden biridir ve dokümanları aramak için araçlar için kalıp oluşturur. Bu sorudaki listenin diğer dillerdeki gibi olması gerekmiyor olabilir.
Axeman

1
autodie çok hoş görünüyor.
j_random_hacker

18

harita - sadece kişinin kodunu daha anlamlı hale getirdiği için değil, aynı zamanda bu "fonksiyonel programlama" hakkında biraz daha fazla şey okumam için bir dürtü verdiği için.


15

Döngülerdeki devam cümlesi. Her döngünün altında, bir sonraki adımda bile yürütülecektir.

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

Benim oyum Perl'in düzenli ifadelerindeki (? {}) Ve (?? {}) gruplarına gidiyordu. Birincisi, dönüş değerini yok sayarak Perl kodunu yürütür, ikincisi, dönüş değerini normal bir ifade olarak kullanarak kodu yürütür.


perl o kadar çok regexp uzantısı icat etti ki diğer programlar artık orijinal regex dili yerine pcre (perl uyumlu regex) kullanıyor.
Saniye

Buradaki küçük bulanıklığı okuyun perldoc.perl.org/… :-D
JJ

Regexps söz konusu olduğunda Perl gerçekten (bildiğim kadarıyla) paketi yönetiyor.
Brad Gilbert

Bu, bildiğim kadarıyla, hala deneyseldir ve gelecekteki Perls'de aynı şekilde çalışmayabilir. Yararlı olmadığını söylemek değil, biraz daha güvenli ve kullanılabilir bir sürüm s /// komutunun / e bayrağında bulunabilir: s/(pattern)/reverse($1);/ge;# hepsini tersine çevirir patterns.
Chris Lutz

@Chris Lutz, @Leon Timmerman: Bu iki yapının artık yeniden canlandığını unutmayın. Ayrıca, ikincisinin artık tekrarlayan kalıpları etkilemek için kullanılmasına gerek olmadığını, şimdi yakalama gruplarında geri çekilebildiğimizi unutmayın. @Brad Gilbert: Bu doğru, PCRE bizi takip etmek için iyi bir iş çıkarsa da; Perl'in tamamen tartışmasız olduğu regex mükemmellik alanlarından biri Unicode özelliklerine erişimidir; birim dağılımımı görün uninames,unichars ve özellikle unipropsne demek sadece bir kısmını görmek için.
tchrist

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

\ G çapa. Bu var sıcak .


3
... ve bir önceki maçın sonunun konumunu gösterir.
Dave Sherohman

1
Ama normal ifadenizi skaler bağlamda çağırmalısınız.
davidnicol

@davidnicol: Yukarıdaki kod çalışır. Ne demek istediğini açıklayabilir misin?
JJ

13

m//Operatör bazı karanlık özel durumları vardır:

  • ?Sınırlayıcı olarak kullanırsanız , aramadığınız sürece yalnızca bir kez eşleşir reset.
  • 'Sınırlayıcı olarak kullanırsanız , desen enterpolasyona tabi tutulmaz.
  • Desen boşsa, son başarılı eşleşmeden gelen deseni kullanır.

2
Bunlar gizli özelliklerden çok gizli yakalamalar gibidir! Onları seven kimseyi tanımıyorum. Bir süre önce p5p'deki bir iş parçacığı, varsayılan bir m / $ foo / r bayrağının yararlılığını tartıştı; burada / r, hiç kimse tek tırnak işaretini hatırlayamadığı için / interpolasyon (harf önemli değildir) anlamına gelmez.
dland

2
@ dland: Kabul etti; Bu gizli yanlış özellikleri çağırırdım ve bunları üretim kodunda asla kullanmazdım.
Michael Carman

7
Bir Perl programcısının tek tırnakların enterpolasyonun olmadığını hatırlayamadığını (hatta tahmin edemediğini) hayal edemiyorum. Bu semantik ile kullanımı, bu şekilde olmasını beklediğim dilde neredeyse evrenseldir ...
sundar - Reinstate Monica

ve eğer desen boşsa ve / o değiştiricisi ile en son başarılı eşleşme derlenmişse, o zamandan itibaren bu desene yapışacaktır.
davidnicol

1
Boş kalıp davranışının reddedildiğini düşünüyorum. Çünkü m / $ foo / gibi bir desen $ foo boş olduğunda kötü bir hata haline gelir.
Matthew S

12

Boş dosya tanıtıcı elmas işleci <> , komut satırı araçları oluşturmada yerini alır. Bir tutamaçtan <FH>okumak gibi davranır , ancak hangisinin sihirli bir şekilde önce bulunursa seçilsin: komut satırı dosya adları veya STDIN. Perlop'tan alınmıştır:

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

4
Ayrıca kullanmanın UNIX anlamsallıktadır "-" Yapabileceğin Yani stdin'den okumak" anlamında. perl myscript.pl file1.txt - file2.txtVe perl ilk dosyayı, ardından Stdin, sonra ikinci dosya işlemek istiyorum.
Ryan C. Thompson

Şunları yapabilirsiniz Kendi nesneler üzerinde operatörü ( ) bir yineleyici gibi işe. Ancak liste bağlamında beklediğiniz gibi çalışmaz. overload<><$var>
dolmen

11

Özel kod blokları gibi BEGIN, CHECKveEND . Awk'tan geliyorlar, ancak Perl'de farklı çalışıyorlar çünkü kayıt tabanlı değil.

BEGINBlok ayrıştırma aşaması için bazı kodlar belirtmek için kullanılabilir; sözdizimi ve değişken denetimi yaptığınızda da yürütülür perl -c. Örneğin, yapılandırma değişkenlerine yüklemek için:

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

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

data.txt.part dosyasını kendimi tekrarlamak zorunda kalmadan data.txt olarak yeniden adlandırır.


10

Biraz belirsiz, skaler bağlamı zorlayan tilde-tilde "operatör" dür.

print ~~ localtime;

aynıdır

print scalar localtime;

ve farklı

print localtime;

5
Bu özellikle belirsizdir, çünkü perl5.10.0 ayrıca ~~normal ifadeler eşleşmeleri yapabilen, bir öğenin bir dizide bulunup bulunmadığını arayabilen "akıllı eşleştirme işleci" ni de tanıtır .
moritz

Bu belirsiz değil, gizlenmiş (ve golf ve JAPH'ler için yararlı).
Michael Carman

Bu doğru değil! ~~ referanslar için güvenli değildir! Onları dizginler.
Leon Timmermans

İyi evet. Dizgi, skaler bağlama zorlandığında referanslara ne olur. "~~ skaler bağlamı zorlar" nasıl yanlış yapar?
Dave Sherohman

3
@Nomad Dervish: Skaler bağlam / = dizgi oluşturma. örneğin "$ n = @a" skaler bağlamdır. "$ s = qq '@ a'" dizgi oluşturmasıdır. Referanslarla ilgili olarak, "$ ref1 = $ ref2" skaler bağlamdır, ancak dizge oluşturmaz.
Michael Carman


9

Perl'in döngü kontrol yapılarının "çaresizlik modu", eşleşen bir etiket bulmak için yığına bakmalarına neden olan Test :: More'un daha iyi veya daha kötü için yararlandığı bazı meraklı davranışlara izin verir.

SKIP: {
    skip() if $something;

    print "Never printed";
}

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

Az bilinen .pmc dosyası var. "Foo kullan", Foo.pm'den önce @INC'de Foo.pmc'yi arayacaktır. Bu öncelikle derlenmiş bayt kodunun yüklenmesine izin vermek için tasarlanmıştır, ancak Module :: Compile bundan daha hızlı yükleme süreleri ve daha kolay hata ayıklama için kaynak filtreli modülleri önbelleğe almak için yararlanır.

Uyarıları hataya dönüştürme yeteneği.

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

Bahsetilmeyen kafamın üstünde düşünebileceğim şey bu.


9

Keçi operatörü *:

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

veya

sub foo {
    return @_;
}

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

Skaler bağlamda liste ataması, atanan listedeki öğelerin sayısını verdiğinden çalışır.

* Not, gerçekten bir operatör değil


Bu şimdiye kadarki en güzel (en az) güzel "operatör" dür.
Chris Lutz
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.