Recursos ocultos do Perl?

143

Quais são alguns recursos de linguagem realmente úteis, mas esotéricos, no Perl que você realmente conseguiu empregar para fazer um trabalho útil?

Diretrizes:

  • Tente limitar as respostas ao núcleo do Perl e não ao CPAN
  • Por favor, dê um exemplo e uma breve descrição

Recursos ocultos também encontrados nos recursos ocultos de outros idiomas:

(Estes são todos da resposta de Corion )

  • C
    • Dispositivo de Duff
    • Portabilidade e Normalidade
  • C #
    • Cotações para listas e cadeias delimitadas por espaço em branco
    • Namespaces aliasable
  • Java
    • Initalizadores estáticos
  • Javascript
    • Funções são cidadãos de primeira classe
    • Escopo e fechamento do bloco
    • Chamando métodos e acessadores indiretamente por meio de uma variável
  • Rubi
    • Definindo métodos através do código
  • PHP
    • Documentação on-line abrangente
    • Métodos mágicos
    • Referências simbólicas
  • Pitão
    • Troca de um valor de linha
    • Capacidade de substituir até funções principais por sua própria funcionalidade

Outros recursos ocultos:

Operadores:

Citando construções:

Sintaxe e nomes:

Módulos, Pragmas e opções de linha de comando:

Variáveis:

Loops e controle de fluxo:

Expressões regulares:

Outras características:

Outros truques e meta-respostas:


Veja também:

Adam Bellaire
fonte
A maioria desses recursos é usada no dia a dia, alguns ocorrem na maioria dos scripts Perl, e a maioria listada em "Outros" ainda é originária de outros idiomas, chamando-os de "ocultos" que alteram a intenção da pergunta.
Reinierpost

Respostas:

54

O operador flip-flop é útil para pular a primeira iteração ao fazer um loop pelos registros (geralmente linhas) retornados por um identificador de arquivo, sem usar uma variável de flag:

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

Execute perldoc perlope pesquise "flip-flop" para obter mais informações e exemplos.

John Siracusa
fonte
Na verdade, que é tomada a partir Awk, onde você pode fazer flip-flop entre dois padrões de escrita pattern1, pattern2
Bruno De Fraine
15
Para esclarecer, o aspecto "escondido" deste é que se o operando para escalar '..' é uma constante o valor é implicitamente em comparação com o número da linha de entrada ($).
Michael Carman
47

Existem muitos recursos não óbvios no Perl.

Por exemplo, você sabia que pode haver um espaço após um sigilo?

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

Ou que você pode dar nomes numéricos secundários se usar referências simbólicas?

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

Há também o operador quase bool "bool", que retorna 1 para expressões verdadeiras e a string vazia para false:

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

Outras coisas interessantes: use overloadvocê pode sobrecarregar literais e números de strings (e, por exemplo, torná-los BigInts ou o que for).

Muitas dessas coisas são realmente documentadas em algum lugar ou seguem logicamente a partir dos recursos documentados, mas mesmo assim algumas não são muito conhecidas.

Atualização : Outra boa. Abaixo, as q{...}construções de citação foram mencionadas, mas você sabia que pode usar letras como delimitadores?

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

Da mesma forma, você pode escrever expressões regulares:

m xabcx
# same as m/abc/
moritz
fonte
2
"Você sabia que pode haver um espaço após um sigilo?" Estou totalmente pasmo. Uau.
Aristóteles Pagaltzis 02/10/08
1
Legal! !! $ undef_var não cria um aviso.
Axeman
4
Eu acho que seu exemplo de utilização de cartas para cordas delimitam deve ser " Apenas um outro hacker perl" em vez de "Jet outro hacker perl" = P
Chris Lutz
A pior parte é que você também pode usar outras coisas como delimitadores. Mesmo parênteses de fechamento. Os seguintes são válidos: s} regex} substituição} xsmg; q] string literal];
22910 Ryan C. Thompson
46

Adicione suporte para arquivos compactados via ARGV mágico :

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;

(aspas em torno de $ _ necessárias para manipular nomes de arquivos com metacaracteres de shell em)

Agora, o <>recurso descompactará qualquer @ARGVarquivo que termine com ".gz" ou ".Z":

while (<>) {
    print;
}
timkay
fonte
2
Eu não acho que você precisa escapar |da substituição.
23711 Chris Lutz
Estou olhando para isso e não consigo descobrir como isso funciona. Em que ponto é zcat |analisado como um comando para canalizar?
Éter
1
@Ether => detecção de tubos é uma característica do aberto dois argumentos, que o operador usa diamantes como ele abre cada arquivo em@ARGV
Eric Strom
40

Um dos meus recursos favoritos no Perl é usar o ||operador booleano para selecionar entre um conjunto de opções.

 $x = $a || $b;

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

Isso significa que se pode escrever:

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

para dar o primeiro verdadeiro valor de $a, $be $c, ou um padrão de 0outra forma.

No Perl 5.10, há também o //operador, que retorna o lado esquerdo, se definido, e o lado direito, caso contrário. Os seguintes seleciona o primeiro definido valor de $a, $b, $c, ou 0de outra forma:

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

Eles também podem ser usados ​​com seus formulários abreviados, que são muito úteis para fornecer padrões:

$ x || = 0; # Se $ x era falso, agora ele tem o valor 0.

$ x // = 0; # Se $ x não tiver sido definido, agora ele tem um valor zero.

Cheerio,

Paulo

pjf
fonte
4
Esse é um idioma tão comum que dificilmente se qualifica como um recurso "oculto".
Michael Carman
3
vergonha a impressora bastante pensa // é um comentário :)
John Ferguson
2
Pergunta, existe um "recurso de uso" para usar esses novos operadores ou eles estão ativados por padrão? Ainda estou apoiando os recursos do Perl 5.10.
JJ
6
// está lá por padrão, sem ajustes especiais necessários. Você também pode fazer o backport para o 5.8.x com o patch dor ... consulte o diretório autores / id / H / HM / HMBRAND / em qualquer espelho CPAN. O FreeBSD 6.xe além disso faz isso para você em seu pacote perl.
dland 2/10/08
2
Quando || ou // é combinado com do {}, você pode encapsular uma atribuição mais complexa, ou seja, $ x = $ a || faça {meu $ z; 3 ou 4 linhas de derivação; $ z};
RET
39

Os operadores ++ e unary - não funcionam apenas em números, mas também em strings.

my $_ = "a"
print -$_

imprime -a

print ++$_

imprime b

$_ = 'z'
print ++$_

imprime aa

Leon Timmermans
fonte
3
Para citar perlvar: "O operador de decremento automático não é mágico." Então --não funciona em strings.
moritz
"aa" não parece ser o elemento natural após "z". Eu esperaria o próximo valor mais alto de ASCII, que é "{".
Éter
4
Não pergunte a um programador o que vem depois de "z"; pergunte a um humano. Esse recurso é ótimo para numerar itens em uma lista longa.
Barry Brown
17
Quando novo no Perl, eu implementei esse recurso com o comportamento exato de z para aa e mostrei a um colega de trabalho que riu de mim e disse: "deixe-me mostrar uma coisa". Chorei um pouco, mas aprendi alguma coisa.
3032 Copas
2
@Ether - Se desejar, use números e os converta automaticamente para ASCII ord(). Ou escreva uma classe pequena e sobrecarregue os operadores para fazer isso por você.
Chris Lutz
36

Como o Perl tem quase todas as partes "esotéricas" das outras listas, vou lhe dizer uma coisa que o Perl não pode:

A única coisa que o Perl não pode fazer é ter URLs arbitrárias vazias no seu código, porque o //operador é usado para expressões regulares.

Para o caso de não ser óbvio para você quais recursos o Perl oferece, aqui está uma lista seletiva das entradas talvez não totalmente óbvias:

Dispositivo de Duff - em Perl

Portabilidade e Normalidade - Provavelmente há mais computadores com Perl do que com um compilador C

Uma classe de manipulação de arquivo / caminho - File :: Find funciona em ainda mais sistemas operacionais do que o .Net

Cotações para listas delimitadas por espaço em branco e cadeias - O Perl permite escolher cotações quase arbitrárias para os delimitadores de lista e cadeia de caracteres

Namespaces aliasable - O Perl possui estes através de atribuições glob:

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

Inicializadores estáticos - o Perl pode executar código em quase todas as fases de compilação e instanciação de objetos, de BEGIN(análise de código) a CHECK(após análise de código) a import(na importação do módulo) a new(instanciação de objeto) a DESTROY(destruição de objeto) a END( destruição de objeto) a (saída do programa)

Funções são cidadãos de primeira classe - assim como em Perl

Escopo e fechamento do bloco - o Perl possui

Chamando métodos e acessadores indiretamente por meio de uma variável - o Perl também faz isso:

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

Definindo métodos através do código - o Perl também permite isso :

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

Documentação on-line abrangente - a documentação do Perl está on-line e provavelmente também no seu sistema

Métodos mágicos que são chamados sempre que você chama uma função "inexistente" - o Perl implementa isso na função AUTOLOAD

Referências simbólicas - é aconselhável ficar longe delas. Eles vão comer seus filhos. Mas é claro que Perl permite que você ofereça seus filhos a demônios sedentos de sangue.

Troca de um valor de linha - Perl permite a atribuição de listas

Capacidade de substituir até funções principais por sua própria funcionalidade

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

ou

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

unlink($_) for @ARGV
Corion
fonte
Sou fã da documentação do Perl em comparação com outros idiomas, mas ainda acho que, para Regexes e referências, isso poderia ser muito racionalizado. por exemplo, o melhor primer para expressões regulares não é perlre, mas perlop
John Ferguson
9
"A única coisa que o Perl não pode fazer é ter URLs arbitrárias vazias no seu código, porque o operador // é usado para expressões regulares." - isso é totalmente absurdo.
É importante ressaltar que, se o seu navegador não possui um navegador compatível com a Internet, por favor, verifique com o administrador do site para obter mais informações. // é usado para expressões regulares em versões Perl até 5.8.x.No 5.10, é redirecionado para definição ou atribuição.
Corion 13/10/08
8
Por que / onde você deseja URLs simples no seu código? Não consigo pensar em um exemplo.
náufrago
18
Ninguém iria querer isso, é apenas um meme Java. " foo.com " é o rótulo http: e depois "foo.com" em um comentário. Algumas pessoas acham isso interessante porque ... elas são burras.
jrockway
35

Autovivificação . AFAIK nenhum outro idioma possui .

JJ
fonte
Eu não tinha ideia de que Python, et al, não suportavam isso.
skiphoppy
@davidnicol: Sério? Você pode fornecer um link? Minha pesquisa rápida no google não retornou nada. Para quem não conhece ECMAscript, é o nome correto para Javascript. en.wikipedia.org/wiki/ECMAScript
JJ
1
E há um módulo para desativar autovivication
Alexandr Ciornii
1
GregG Lind - Dado que o Python cria automaticamente variáveis ​​sempre que você as atribui, a ativação automática criaria problemas monstruosos a partir de um único erro de digitação.
23720 Chris Lutz
3
@tchrist - a = [[x * y para y em xrange (1,11)] para x em xrange (1,11)]
Omnifarious
31

É simples citar quase todo tipo de string estranha no Perl.

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

De fato, os vários mecanismos de citação no Perl são bastante interessantes. Os mecanismos de cotação do tipo regex do Perl permitem que você cite qualquer coisa, especificando os delimitadores. Você pode usar quase qualquer caractere especial como #, /, ou abrir / fechar caracteres como (), [] ou {}. Exemplos:

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

Mecanismos de citação:

q: citação literal; único caractere que precisa ser escapado é o caractere final. qq: uma cotação interpretada; processa variáveis ​​e caracteres de escape. Ótimo para strings que você precisa citar:

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

qx: funciona como qq, mas o executa como um comando do sistema, não interativamente. Retorna todo o texto gerado a partir da saída padrão. (Redirecionamento, se suportado no sistema operacional, também sai) Também feito com aspas (o caracter `).

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

qr: interpreta como qq, mas depois o compila como uma expressão regular. Também trabalha com as várias opções no regex. Agora você pode passar a regex como uma variável:

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: um operador de cotação muito, muito útil. Transforma um conjunto de palavras separadas por espaços em branco em uma lista. Ótimo para preencher dados em um teste de unidade.


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

Eles são ótimos para usá-los sempre que isso torna as coisas mais claras. Para qx, qq eq, provavelmente utilizo os operadores {}. O hábito mais comum das pessoas que usam qw geralmente é o operador (), mas às vezes você também vê qw //.

Robert P
fonte
1
Às vezes eu uso qw "" para que os marcadores de sintaxe o realcem corretamente.
Brad Gilbert
Funciona para mim no SlickEdit. :)
Robert P
1
@fengshaun, os editores Eu geralmente uso Do destacar estes corretamente. Eu estava me referindo, em parte ao marcador de sintaxe no StackOverflow.
Brad Gilbert
@ Brad Gilbert: estouro de pilha não pode (bem, (não) parse pena Perl diddly agachamento ☹.
tchrist
my $moreout = qx{type "$path" 2>&1};... Eu não sabia que você poderia fazer isso! [TM]
dland
27

Não é realmente oculto, mas muitos programadores Perl todos os dias não conhecem o CPAN . Isso se aplica especialmente a pessoas que não são programadores em período integral ou não programam em Perl em período integral.

mpeters
fonte
27

A instrução "for" pode ser usada da mesma maneira que "with" é usada no Pascal:

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

Você pode aplicar uma sequência de operações s /// etc. à mesma variável sem precisar repetir o nome da variável.

NOTA: o espaço ininterrupto acima (& nbsp;) ocultou o Unicode para contornar o Markdown. Não copie e cole :)

timkay
fonte
E "map" também faz o mesmo truque ... map {....} $ item; Uma vantagem de usar o mapa "for" over "" seria que você poderia usar o próximo para sair.
draegtun
2
Além disso, para o item que está sendo manipulado está listado antes do código fazer a manipulação, levando a uma melhor legibilidade.
Robert P
@RobertP: Isso mesmo. Um tópico é útil no discurso.
tchrist
26

O operador de palavra-chave é uma das minhas coisas favoritas. Comparar:

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

e

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

Muito menos ruído, mais fácil para os olhos. Outra coisa muito legal sobre o Perl, que realmente falta quando se escreve SQL, é que uma vírgula à direita é legal:

print 1, 2, 3, ;

Isso parece estranho, mas não se você recuar o código de outra maneira:

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

A adição de um argumento adicional à chamada de função não exige que você use vírgulas nas linhas anteriores ou finais. A mudança de linha única não afeta as linhas adjacentes.

Isso torna muito agradável trabalhar com funções variadas. Este é talvez um dos recursos mais subestimados do Perl.

dland
fonte
2
Um caso interessante da sintaxe do Perl é que o seguinte é válido: para $ _ qw (uma lista de itens) {...}
ephemient
1
Você pode até abusar da sintaxe global para citar palavras, desde que não use caracteres especiais como * ?. Então você pode escreverfor (<a list of stuff>) { ... }
Moritz
1
@hemphient: quase. Isso só funciona com lexicals: para minha US $ x qw (abc) {...} Por exemplo: por US $ _ qw (abc) {impressão} # imprime nada
dland
por que adicionar esse léxico extra quando você pode desfrutar do padrão favorito do perl? para (qw / abcd /) {print; }
fengshaun
2
@hemhemient, @fengshaun, @moritz, @dland: Isso é “fixo” no blead ; veja este tópico p5p .
2018
26

A capacidade de analisar dados colados diretamente em um bloco DATA . Não há necessidade de salvar em um arquivo de teste para ser aberto no programa ou similar. Por exemplo:

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

__DATA__
some good data
some bad data
more good data 
more good data 
allan
fonte
E muito útil em pequenos testes!
Fengshaun
@ Peter Mortensen como você teria vários blocos? E como você termina um bloco?
Toad
@Carga: é a resposta de allan (veja a lista de revisões). É melhor abordar esse usuário. Ou, como esse usuário deixou o Stack Overflow, talvez não atenda a ninguém em particular (para que um verdadeiro especialista em Perl possa corrigi-lo mais tarde).
Peter Mortensen
3
@Hai: Não, não é feio - na verdade, é precisamente o oposto de feio: é limpo, esbelto, minimalista e bonito; em uma palavra, é maravilhoso, e idiomas sem ele são uma PITA. @ Peter Mortensen, @ Toad: Uma resposta para como ter vários blocos de dados no mesmo programa é usar o módulo Inline :: Files do CPAN.
tchrist
Inline :: Files é implementado usando filtros de origem. Há também Data :: Section que fornece vários blocos embutidos e não usa filtros de origem.
Prakash K
24

Novas operações de bloco

Eu diria que a capacidade de expandir o idioma, criando operações de pseudo-bloco, é uma delas.

  1. Você declara o protótipo para um sub indicando que ele recebe uma referência de código primeiro:

    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. Você pode chamá-lo no corpo assim

    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é outra jóia semi-oculta.) Observe como você não precisa dasub palavra chave na frente do bloco ou da vírgula antes do hash. Ele acaba parecendo muito com:map { } @list

Filtros de origem

Além disso, existem filtros de origem. Onde o Perl passará o código para você poder manipulá-lo. Tanto isso quanto as operações de bloco são basicamente coisas do tipo não tente fazer isso em casa.

Fiz algumas coisas bacanas com os filtros de origem, por exemplo, como criar uma linguagem muito simples para verificar o tempo, permitindo linhas curtas de Perl para algumas tomadas de decisão:

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

Lib::TL iria apenas procurar as "variáveis" e as constantes, criá-las e substituí-las conforme necessário.

Novamente, os filtros de origem podem ser confusos, mas são poderosos. Mas eles podem atrapalhar os depuradores com algo terrível - e até avisos podem ser impressos com os números de linha incorretos. Eu parei de usar o Switch de Damian porque o depurador perderia toda a capacidade de me dizer onde eu realmente estava. Mas descobri que você pode minimizar o dano modificando pequenas seções do código, mantendo-os na mesma linha.

Ganchos de sinal

Muitas vezes é feito o suficiente, mas não é tão óbvio. Aqui está um manipulador de matrizes que apóia o antigo.

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

Isso significa que sempre que algum outro módulo do código quer morrer, eles precisam chegar até você (a menos que alguém faça uma substituição destrutiva em $SIG{__DIE__} ). E você pode ser notificado de que alguém coloca algo em erro.

Obviamente, para coisas suficientes, você pode usar apenas um END { }bloco, se tudo o que você quer fazer é limpar.

overload::constant

Você pode inspecionar literais de um determinado tipo em pacotes que incluem seu módulo. Por exemplo, se você usar isso em seu importsub:

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

isso significa que todo número inteiro maior que 2 bilhões nos pacotes de chamada será alterado para um Math::BigIntobjeto. (Veja sobrecarga :: constante ).

Literais Inteiros Agrupados

Enquanto estamos nisso. O Perl permite dividir grandes números em grupos de três dígitos e ainda assim obter um número inteiro analisável. Nota 2_000_000_000acima para 2 bilhões.

Axeman
fonte
5
Ao usar os manipuladores $ SIG { DIE }, é altamente recomendável que você inspecione $ ^ S para ver se seu programa está realmente morrendo ou apenas lançando uma exceção que será capturada. Geralmente você não quer interferir com o último.
pjf 2/10/08
O novo bloco é muito instrutivo! Eu estava pensando que era uma linguagem semântica! Muito Obrigado.
ZeroCool
Um uso instrutivo do filtro de origem é o NiceSlice do pdl ( pdl.perl.org/?docs=NiceSlice&title=PDL::NiceSlice ) para que não seja necessário usar o ->slicemétodo como sempre que uma fatia é necessária.
Joel Berger
24

Binário "x" é o operador de repetição :

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

Também funciona com listas:

print for (1, 4, 9) x 3; # print 149149149
Bruno De Fraine
fonte
Essa é uma das razões pelas quais o Perl tem sido tão popular entre os hackers. perl -e 'imprime 0x000 x 25';
JJ
4
Meu uso favorito para isso é gerar espaços reservados para a última parte de uma instrução SQL INSERT: @p = ('?') X $ n; $ p = junção (",", @p); $ sql = "INSERIR ... VALORES ($ p)";
Skiphoppy
24

Verificação de contaminação. Com a verificação de contaminação ativada, o perl morre (ou avisa, com-t ) se você tentar passar dados contaminados (grosso modo, dados de fora do programa) para uma função não segura (abrir um arquivo, executar um comando externo, etc.). É muito útil ao escrever scripts setuid ou CGIs ou qualquer coisa em que o script tenha maiores privilégios do que a pessoa que os alimenta.

Magic goto. goto &subfaz uma chamada de cauda otimizada.

O depurador.

use stricte use warnings. Isso pode salvá-lo de vários erros de digitação.

Glomek
fonte
1
Por que outros idiomas não têm esse recurso? Esse recurso usado torna os scripts da Web em perl uma ordem de magnitude mais segura.
Matthew Bloqueio
22

Com base na maneira como os switches "-n"e "-p"são implementados no Perl 5, você pode escrever um programa aparentemente incorreto, incluindo }{:

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

que é convertido internamente para este código:

LINE: while (defined($_ = <ARGV>)) {
    print $_; }{ print "$. Files";
}
seg
fonte
@martin clayton: Por que é chamado assim?
tchrist
@ tchrist - porque, supostamente, parece duas pessoas esfregando o nariz. De perfil, se você entende o que quero dizer.
martin clayton
18

Vamos começar com facilidade com o operador de nave espacial .

$a = 5 <=> 7;  # $a is set to -1
$a = 7 <=> 5;  # $a is set to 1
$a = 6 <=> 6;  # $a is set to 0
Sec
fonte
1
@ Leon: C / C ++ não faz um retorno de 3 valores para números. Se a memória serve, as funções comapre String são o único retorno de 3 valores que conheço em toda a linguagem STL. O AFAIK Python não possui uma comparação numérica de retorno 3. O Java também não tem uma comparação de retorno específica de número 3.
JJ
7
Vale mencionar o que há de tão útil nos operadores de comparação -1/0/1, já que nem todo mundo pode saber: você pode encadear eles com o operador or para fazer o primário / secundário / etc. sortes. Classifica as ($a->lname cmp $b->lname) || ($a->fname cmp $b->fname)pessoas pelo sobrenome, mas se duas pessoas tiverem o mesmo sobrenome, elas serão ordenadas pelo primeiro nome.
hobbs
O @JJ Python possui uma comparação de 3 valores: cmp () >>> print (cmp (5,7), cmp (6,6), cmp (7,5)) (-1, 0, 1)
bukzor
18

Esta é uma meta-resposta, mas o Perl Tips arquivos contêm todos os tipos de truques interessantes que podem ser feitos com o Perl. O arquivo das dicas anteriores está on-line para navegação e pode ser assinado via lista de discussão ou feed Atom.

Algumas das minhas dicas favoritas incluem a criação de executáveis ​​com o PAR , o uso de autodie para gerar exceções automaticamente e o uso dos comutadores e construções de correspondência inteligente no Perl 5.10.

Divulgação: sou um dos autores e mantenedores do Perl Tips, então obviamente penso muito bem neles. ;)

pjf
fonte
2
Provavelmente, é um dos melhores idiomas documentados do mercado e define o padrão das ferramentas para pesquisar na documentação. Que a lista nesta pergunta provavelmente não é tão necessária quanto em outros idiomas.
Axeman
1
autodie parece muito bom.
j_random_hacker
18

mapa - não apenas porque torna o código mais expressivo, mas porque me deu um impulso de ler um pouco mais sobre essa "programação funcional".

brunorc
fonte
15

A cláusula continue nos loops. Ele será executado na parte inferior de cada loop, mesmo nos próximos.

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

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

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

Meu voto seria para os grupos (? {}) E (?? {}) nas expressões regulares do Perl. O primeiro executa o código Perl, ignorando o valor de retorno, o segundo executa o código, usando o valor de retorno como uma expressão regular.

Leon Timmermans
fonte
O perl inventou tantas extensões regexp que agora outros programas costumam usar pcre (regex compatível com perl) em vez da linguagem regex original.
Sec
Leia a pequena sinopse aqui perldoc.perl.org/… :-D
JJ
Perl realmente tem (até onde eu sei) liderar o grupo, quando se trata de regexps.
Brad Gilbert
Até onde sei, isso ainda é experimental e pode não funcionar da mesma maneira no futuro Perls. Para não dizer que não é útil, mas uma versão um pouco mais segura e utilizável pode ser encontrada na bandeira / s do comando ///: s/(pattern)/reverse($1);/ge;# inverte tudo patterns.
9309 Chris Lutz
@ Chris Lutz, @ Leon Timmerman: Observe que essas duas construções agora são remanescentes. Observe também que o segundo não precisa mais ser usado para efetuar padrões recursivos, agora que podemos recursar em grupos de captura. @ Brad Gilbert: Isso mesmo, embora o PCRE faça um trabalho decente em nos rastrear; uma área de excelência em regex em que o Perl é completamente incontestável é o acesso às propriedades Unicode; ver minha distribuição unitrio de uninames, unicharse, especialmente, unipropspara ver apenas uma parte do que quero dizer.
tchrist
13
while(/\G(\b\w*\b)/g) {
     print "$1\n";
}

a âncora \ G. Está quente .

JJ
fonte
3
... e indica a posição do final da partida anterior.
Dave Sherohman 02/10/08
1
Mas você deve chamar seu regex no contexto escalar.
Davidnicol 03/10/08
@ Davidnicol: O código acima funciona. Você pode esclarecer o que quer dizer?
JJ
13

O m//operador tem alguns casos especiais obscuros:

  • Se você usar ?como delimitador, ele corresponderá apenas uma vez, a menos que você chamereset .
  • Se você usar ' como delimitador, o padrão não será interpolado.
  • Se o padrão estiver vazio, ele usará o padrão da última correspondência bem-sucedida.
Michael Carman
fonte
2
São mais como truques ocultos do que recursos ocultos! Eu não conheço ninguém que gosta deles. Algum tempo atrás, um tópico na p5p discutia a utilidade de um sinal putativo m / $ foo / r, em que / r significaria nenhuma interpolação (a letra não é importante), pois ninguém consegue se lembrar da coisa de aspas simples.
dland 2/10/08
2
@land: De acordo; Eu chamo esses escondidos mis características e nunca iria usá-los no código de produção.
Michael Carman
7
Não consigo imaginar um programador Perl incapaz de lembrar (ou até adivinhar) que aspas simples não representam interpolação. Seu uso com esta semântica é quase universal na língua que eu prefiro esperar que isso seja assim ...
sundar - Reintegrar Monica
e se o padrão estiver vazio e a última correspondência bem-sucedida foi compilada com o modificador / o, a partir de então ele ficará preso nesse padrão.
Davidnicol 03/10/08
1
Eu acho que o comportamento do padrão vazio foi preterido. Principalmente porque um padrão como m / $ foo / se torna um bug desagradável quando $ foo está vazio.
Matthew S
12

O operador de diamante nulo filehandle <>tem seu lugar na construção de ferramentas de linha de comando. Ele age como <FH>leitura de um identificador, exceto que ele seleciona magicamente o que for encontrado primeiro: nomes de arquivos de linha de comando ou STDIN. Retirado de perlop:

while (<>) {
...         # code for each line
}
Spoulson
fonte
4
Ele também segue a semântica UNIX de usar "-" para significar "ler de stdin Então você poderia fazer. perl myscript.pl file1.txt - file2.txt, E perl iria processar o primeiro arquivo, em seguida, stdin, em seguida, o segundo arquivo.
Ryan C. Thompson
Você pode operar overloado <>operador com seus próprios objetos ( <$var>) como um iterador. No entanto, ele não funciona como você poderia esperar no contexto da lista.
dólmen
11

Blocos de código especiais como BEGIN, CHECKe END. Eles vêm do Awk, mas funcionam de maneira diferente no Perl, porque não é baseado em registros.

O BEGINbloco pode ser usado para especificar algum código para a fase de análise; também é executado quando você faz a verificação de sintaxe e variável perl -c. Por exemplo, para carregar variáveis ​​de configuração:

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

renomeia data.txt.part para data.txt sem ter que me repetir.

timkay
fonte
10

Um pouco obscuro é o operador "til-til" que força o contexto escalar.

print ~~ localtime;

é o mesmo que

print scalar localtime;

e diferente de

print localtime;
Sec
fonte
5
Isso é especialmente obscuro porque o perl5.10.0 também apresenta o "operador de correspondência inteligente" ~~, que pode fazer correspondências de expressões regulares, pode procurar se um item está contido em uma matriz e assim por diante.
Moritz
Isso não é obscuro, é ofuscado (e útil para golfe e JAPHs).
Michael Carman
Isso não está correto! ~~ não é seguro em referências! Ele os especifica.
9114 Leon Timmermans
Bem, sim. Stringification é o que acontece com as referências quando forçadas ao contexto escalar. Como isso faz com que "~~ force o contexto escalar" incorreto?
Dave Sherohman 02/10/08
3
@ Nomad Dervish: contexto escalar / = stringification. por exemplo, "$ n = @a" é um contexto escalar. "$ s = qq '@ a'" é uma string. No que diz respeito às referências, "$ ref1 = $ ref2" é um contexto escalar, mas não especifica.
Michael Carman
9

tie, a interface de vinculação variável.

davidnicol
fonte
Gravata :: O arquivo salvou meu dia uma vez!
Mhd 03/03
9

O "modo de desespero" das construções de controle de loop do Perl, que faz com que eles procurem na pilha para encontrar um rótulo correspondente, permite alguns comportamentos curiosos dos quais o Test :: More tira proveito, para o bem ou para o mal.

SKIP: {
    skip() if $something;

    print "Never printed";
}

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

Existe o pouco conhecido arquivo .pmc. "use Foo" procurará Foo.pmc no @INC antes de Foo.pm. O objetivo era permitir que o bytecode compilado fosse carregado primeiro, mas o Module :: Compile tira vantagem disso para armazenar em cache os módulos filtrados de origem para tempos de carregamento mais rápidos e depuração mais fácil.

A capacidade de transformar avisos em erros.

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

É nisso que consigo pensar em cima da minha cabeça que não foi mencionado.

Schwern
fonte
9

O operador de cabra *:

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

ou

sub foo {
    return @_;
}

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

Funciona porque a atribuição de lista no contexto escalar gera o número de elementos na lista que está sendo atribuída.

* Observe que não é realmente um operador

Chas. Owens
fonte
Esse é o "operador" mais (bem, menos) mais bonito de todos os tempos.
24720 Chris Lutz