Como a impressão do Perl pode adicionar uma nova linha por padrão?

95

Em Perl, a maioria das minhas printdeclarações assume a forma

print "hello." . "\n";

Existe uma boa maneira de evitar manter todos os "\ n" incômodos espalhados por aí?

Eu sei que poderia fazer uma nova função como a myprintque adiciona automaticamente \ n, mas seria bom se eu pudesse substituir a existente print.

Mike
fonte
10
Se sua resposta incluir $ \, certifique-se de que vem com uma lista de advertências sobre a configuração de variáveis ​​globais com efeito invisível. Embora seja muito inteligente e tecnicamente responda à pergunta, também é muito perigoso entregá-lo sem qualificação a um novato.
Schwern
1
perldoc perlvardescreve a maioria das advertências, por que trabalhá-las aqui?
David M
5
@David, porque algum hacker aleatório pesquisará as respostas aqui em vez de perldoc, ficará satisfeito com elas e nem mesmo saberá das advertências!
P Shved
2
Esse é exatamente o tipo de raciocínio bizarro que resultou em meu ferro de passar ter uma etiqueta de advertência de que não devo passar roupas enquanto as estiver usando.
David M
8
As ferramentas da vida real têm limitações físicas que são razoavelmente bem compreendidas por pessoas que viveram suas vidas no mundo físico. As ferramentas de software não têm essas limitações e não existem regras. Eles podem fazer qualquer coisa e freqüentemente se comportam fora das expectativas, especialmente para iniciantes que ainda não aprenderam os limites das expectativas razoáveis.
Ether

Respostas:

99

Perl 6 tem a sayfunção que adiciona automaticamente \n.

Você também pode usar sayem Perl 5.10 ou 5.12 se adicionar

use feature qw(say);

para o início do seu programa. Ou você pode usar Modern :: Perl para obter este e outros recursos.

Veja o recurso perldoc para mais detalhes.

Josh Kelley
fonte
7
Na verdade, tudo que você tem a fazer é use 5.012;ou use 5.010;para obtê-lo se você estiver executando essas mais recentes perls.
Robert P
Não é seguro assumir que, a menos que Perl 6 seja especificamente mencionado, a questão se refere a Perl 5?
wobbily_col
35

Você pode usar a -lopção no cabeçalho she-bang:

#!/usr/bin/perl -l

$text = "hello";

print $text;
print $text;

Resultado:

hello
hello
Jaypal Singh
fonte
3
Muito agradável. Mais sobre as perlopções, incluindo o que -lestá fazendo, aqui .
ruffin
1
Por ser global, essa é uma prática ruim em qualquer coisa, exceto em uma linha e nos menores dos scripts.
Schwern
24

Se Perl 5.10+ não for uma opção, aqui está uma aproximação rápida e suja. Não é exatamente o mesmo, já que digamos que tem alguma mágica quando seu primeiro argumento é um identificador, mas para imprimir em STDOUT:

sub say {print @_, "\n"}

say 'hello';
Eric Strom
fonte
20

A maneira como você está escrevendo sua declaração de impressão é desnecessariamente prolixa. Não há necessidade de separar a nova linha em sua própria string. Isso é suficiente.

print "hello.\n";

Essa constatação provavelmente tornará sua codificação mais fácil em geral.

Além de usar use feature "say"ou use 5.10.0ou use Modern::Perlpara obter o sayrecurso embutido , irei manipular o perl5i, que ativa muitos recursos sensíveis ausentes do Perl 5 por padrão.

Schwern
fonte
9

Talvez você queira alterar o separador de registro de saída para alimentação de linha com:

local $\ = "\n";

$ perl -e 'print q{hello};print q{goodbye}' | od -c
0000000    h   e   l   l   o   g   o   o   d   b   y   e                
0000014
$ perl -e '$\ = qq{\n}; print q{hello};print q{goodbye}' | od -c
0000000    h   e   l   l   o  \n   g   o   o   d   b   y   e  \n        
0000016

Atualização: minha resposta fala mais sobre capacidade do que sobre conveniência. Não considero que adicionar "\ n" no final das linhas seja uma tarefa "incômoda", mas se alguém realmente quiser evitá-los, esta é uma maneira. Se eu tivesse que manter um pouco de código que usa essa técnica, provavelmente o refatoraria imediatamente.

David M
fonte
6
Não, por favor, não faça isso. Embora seja tecnicamente uma resposta correta, usar uma variável especial para algo tão trivial quanto isso é um fardo de manutenção no futuro.
ver
1
@t see Eu concordo completamente, na verdade. Como editei minha resposta para indicar, minha resposta descreve a capacidade, mesmo que não seja recomendada como prática geral.
David M
O perigo real vem do fato de que todo código agora incluirá novas linhas, até mesmo códigos em módulos de outras pessoas que não esperavam por isso. Imagine um código de rede que teria enviado a mensagem "helo\r\n"que agora envia "helo\r\n\n".
Chas. Owens
Claro que você sempre pode torná-lo local para evitar afetar outro código, mas ainda deseja fazer sua sub-rotina parecer um pouco mais limpa:local $\ = "\n";
redbmk
Usar o sinalizador de comando -lé ótimo para linhas de comando (consulte perldoc.perl.org/perlrun.html#Command-Switches ). Eu não o recomendaria em nenhum programa maior.
djd
4

Aqui está o que encontrei em https://perldoc.perl.org/perlvar.html :

$ \ O separador de registro de saída para o operador de impressão. Se definido, este valor é impresso após o último dos argumentos de impressão. O padrão é undef.

Você não pode chamar output_record_separator () em um identificador, apenas como um método estático. Consulte IO :: Handle.

Mnemônico: você define $ \ em vez de adicionar "\ n" no final da impressão. Além disso, é como $ /, mas é o que você recebe "de volta" do Perl.

exemplo:

$\ = "\n";
print "a newline will be appended to the end of this line automatically";
hofergabriel
fonte
3

Em Perl 6 existe a sayfunção

Michael Mrozek
fonte
16
Também está em
5.010
1

Se você estiver preso ao pré-5.10, as soluções fornecidas acima não replicarão totalmente a sayfunção. Por exemplo

sub say { print @_, "\n"; }

Não funcionará com invocações como

say for @arr;

ou

for (@arr) {
    say;
}

... porque a função acima não atua na função global implícita $_like printe real say.

Para replicar mais de perto o perl 5.10+ sayvocê quer esta função

sub say {
    if (@_) { print @_, "\n"; }
    else { print $_, "\n"; }
}

Que agora age assim

my @arr = qw( alpha beta gamma );
say @arr;
# OUTPUT
# alphabetagamma
#
say for @arr;
# OUTPUT
# alpha
# beta
# gamma
#

O sayintegrado em perl6 se comporta de maneira um pouco diferente. Invocá-lo com say @arrou @arr.saynão apenas concatenará os itens do array, mas os imprimirá separados pelo separador de lista. Para replicar isso em perl5 você faria isso

sub say {
    if (@_) { print join($", @_) . "\n"; }
    else { print $_ . "\n"; }
}

$"é a variável separadora de lista global ou, se você estiver usando English.pm, é é$LIST_SEPARATOR

Agora vai agir mais como perl6,

say @arr;
# OUTPUT
# alpha beta gamma
#
Joshua
fonte