W jaki sposób druk Perla może domyślnie dodać nowy wiersz?

96

W Perlu większość moich printwypowiedzi ma formę

print "hello." . "\n";

Czy istnieje dobry sposób, aby uniknąć trzymania wszystkich nieznośnych "\ n" kłamstw?

Wiem, że mógłbym stworzyć nową funkcję, taką jak ta, myprintktóra automatycznie dodaje \ n, ale byłoby miło, gdybym mógł zastąpić istniejącą print.

Mikrofon
źródło
10
Jeśli Twoja odpowiedź zawiera $ \, upewnij się, że zawiera ona listę zastrzeżeń dotyczących ustawiania zmiennych globalnych z niewidocznym efektem. Chociaż jest bardzo sprytny i technicznie odpowiada na pytanie, jest również bardzo niebezpieczny w przekazaniu nowicjuszowi bez kwalifikacji.
Schwern
1
perldoc perlvaropisuje większość zastrzeżeń, po co je tutaj omawiać?
David M
5
@David, ponieważ jakiś przypadkowy haker wygoogluje tutaj odpowiedzi zamiast perldoc, będzie z nich zadowolony, a nawet nie będzie wiedział o zastrzeżeniach!
P Shved
2
To jest dokładnie ten rodzaj dziwacznego rozumowania, które doprowadziło do tego, że moje żelazko miało etykietę ostrzegawczą, że nie powinienem prasować ubrań, gdy je noszę.
David M
8
Rzeczywiste narzędzia mają fizyczne ograniczenia, które są dość dobrze rozumiane przez ludzi, którzy żyli w świecie fizycznym. Narzędzia programowe nie podlegają takim ograniczeniom i nie ma żadnych reguł. Potrafią wszystko i często zachowują się poza oczekiwaniami, zwłaszcza dla początkujących, którzy nie poznali jeszcze granic rozsądnych oczekiwań.
Ether

Odpowiedzi:

101

Perl 6 ma sayfunkcję, która automatycznie dołącza \n.

Możesz również używać sayw Perl 5.10 lub 5.12, jeśli dodasz

use feature qw(say);

na początek programu. Lub możesz użyć Modern :: Perl, aby uzyskać tę i inne funkcje.

Więcej szczegółów znajdziesz w opisie funkcji perldoc .

Josh Kelley
źródło
7
W rzeczywistości, wszystko co musisz zrobić, to use 5.012;albo use 5.010;je zdobyć, jeśli używasz tych nowszych perls.
Robert P
Czy nie można bezpiecznie założyć, że jeśli nie wspomniano wyraźnie o Perlu 6, pytanie dotyczy Perla 5?
wobbily_col
37

Możesz użyć -lopcji w nagłówku she-bang:

#!/usr/bin/perl -l

$text = "hello";

print $text;
print $text;

Wynik:

hello
hello
jaypal singh
źródło
3
Bardzo dobrze. Więcej informacji o perlopcjach, w tym o tym, co -lrobi, znajdziesz tutaj .
ruffin
2
Ponieważ jest to globalne, jest to zła praktyka w czymkolwiek poza jednowierszowymi i najmniejszymi skryptami.
Schwern
24

Jeśli Perl 5.10+ nie wchodzi w grę, oto szybkie i brudne przybliżenie. To nie jest dokładnie to samo, ponieważ powiedz, że ma trochę magii, gdy jego pierwszy argument jest uchwytem, ​​ale do drukowania na STDOUT:

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

say 'hello';
Eric Strom
źródło
20

Sposób, w jaki piszesz wyciąg do druku, jest niepotrzebnie rozwlekły. Nie ma potrzeby oddzielania nowej linii do własnego ciągu. To wystarczy.

print "hello.\n";

Ta świadomość prawdopodobnie ogólnie ułatwi ci kodowanie.

Oprócz używania use feature "say"lub use 5.10.0lub w use Modern::Perlcelu uzyskania wbudowanej sayfunkcji, zamierzam pimp perl5i, który domyślnie włącza wiele rozsądnych brakujących funkcji Perl 5.

Schwern
źródło
10

Być może chcesz zmienić separator rekordów wyjściowych na nowy wiersz za pomocą:

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

Aktualizacja: moja odpowiedź mówi raczej o zdolności niż celowości. Nie uważam, aby dodawanie „\ n” na końcu linii było „brzydkim” obowiązkiem, ale jeśli ktoś naprawdę chce ich uniknąć, to jest jeden ze sposobów. Gdybym musiał utrzymywać fragment kodu wykorzystujący tę technikę, prawdopodobnie zrefaktorowałbym go natychmiast.

David M.
źródło
6
Nie, proszę, nie rób tego. Chociaż technicznie poprawna odpowiedź, użycie specjalnej zmiennej do czegoś tak trywialnego, jak to, jest obciążeniem związanym z utrzymaniem w przyszłości.
tsee
1
@tsee Zgadzam się całkowicie. Kiedy zredagowałem odpowiedź, aby wskazać, moja odpowiedź opisuje tę zdolność, nawet jeśli nie zaleca się jej jako ogólnej praktyki.
David M
Prawdziwe niebezpieczeństwo polega na tym, że cały kod będzie teraz dodawać nowe linie, nawet kod w modułach innych osób, który się tego nie spodziewał. Wyobraź sobie kod sieciowy, który wysłałby wiadomość, "helo\r\n"którą teraz wysyła "helo\r\n\n".
Chas. Owens
Oczywiście zawsze możesz ustawić go lokalnie, aby uniknąć wpływania na inny kod, ale nadal chcesz, aby twój podprogram wyglądał trochę local $\ = "\n";
czysto
Używanie flagi polecenia -ljest świetne w przypadku jednowierszowych linii poleceń (patrz perldoc.perl.org/perlrun.html#Command-Switches ). Nie polecałbym tego w żadnym większym programie.
djd
4

Oto co znalazłem na https://perldoc.perl.org/perlvar.html :

$ \ Separator rekordów wyjściowych dla operatora drukowania. Jeśli zdefiniowano, wartość ta jest drukowana po ostatnim z argumentów print. Domyślnie jest to undef.

Nie możesz wywołać output_record_separator () na dojściu, tylko jako metoda statyczna. Zobacz IO :: Handle.

Mnemonic: ustawiasz $ \ zamiast dodawać "\ n" na końcu wydruku. Poza tym jest podobny do $ /, ale to jest to, co dostajesz „z powrotem” od Perla.

przykład:

$\ = "\n";
print "a newline will be appended to the end of this line automatically";
hofergabriel
źródło
3

W Perlu 6 jest sayfunkcja

Michał Mrozek
źródło
16
Jest też w
5.010
1

Jeśli utkniesz w wersji wcześniejszej niż 5.10, powyższe rozwiązania nie będą w pełni replikować tej sayfunkcji. Na przykład

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

Nie będzie działać z wywołaniami, takimi jak

say for @arr;

lub

for (@arr) {
    say;
}

... ponieważ powyższa funkcja nie działa na niejawne $_podobne globalne printi rzeczywistą sayfunkcję.

Aby dokładniej powielić perl 5.10+ say, potrzebujesz tej funkcji

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

Który teraz działa w ten sposób

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

sayWbudowane w perl6 zachowuje się trochę inaczej. Wywołanie go za pomocą say @arrlub @arr.saynie tylko połączy elementy tablicy, ale zamiast tego drukuje je oddzielone separatorem listy. Aby powielić to w perl5, zrobiłbyś to

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

$"jest zmienną globalnego separatora listy lub, jeśli używasz, English.pmto jest$LIST_SEPARATOR

Będzie teraz zachowywał się bardziej jak perl6

say @arr;
# OUTPUT
# alpha beta gamma
#
Joshua
źródło