Bagaimana Perl's print menambahkan baris baru secara default?

95

Di Perl sebagian besar printpernyataan saya berbentuk

print "hello." . "\n";

Adakah cara yang bagus untuk menghindari menyimpan semua "\ n" yang mengganggu?

Saya tahu saya bisa membuat fungsi baru seperti myprintyang secara otomatis menambahkan \ n, tapi alangkah baiknya jika saya bisa menimpa yang sudah ada print.

Mike
sumber
10
Jika jawaban Anda menyertakan $ \ pastikan jawaban itu disertai dengan daftar peringatan tentang menyetel variabel global dengan efek tak terlihat. Meskipun sangat pintar dan secara teknis menjawab pertanyaan tersebut, juga sangat berbahaya untuk menyerahkan tanpa kualifikasi kepada seorang pemula.
Schwern
1
perldoc perlvarmenjelaskan sebagian besar peringatan, mengapa membahasnya di sini?
David M
5
@David, karena beberapa peretas acak akan mencari jawaban di Google di sini alih-alih perldoc, puas dengan mereka, dan bahkan tidak akan tahu tentang peringatan!
P Shved
2
Itulah alasan aneh yang menyebabkan setrika saya memiliki label peringatan bahwa saya tidak boleh menyetrika pakaian saat saya memakainya.
David M
8
Peralatan kehidupan nyata memiliki keterbatasan fisik yang dapat dipahami dengan baik oleh orang-orang yang telah menjalani kehidupan mereka di dunia fisik. Alat perangkat lunak tidak terikat oleh batasan seperti itu, dan tidak ada aturan apa pun. Mereka dapat melakukan apa saja, dan sering berperilaku di luar ekspektasi, terutama bagi pemula yang belum mempelajari batasan ekspektasi yang wajar.
Eter

Jawaban:

99

Perl 6 memiliki sayfungsi yang ditambahkan secara otomatis \n.

Anda juga dapat menggunakan saydi Perl 5.10 atau 5.12 jika Anda menambahkan

use feature qw(say);

ke awal program Anda. Atau Anda dapat menggunakan Modern :: Perl untuk mendapatkan ini dan fitur lainnya.

Lihat fitur perldoc untuk lebih jelasnya.

Josh Kelley
sumber
7
Faktanya, yang harus Anda lakukan adalah use 5.012;atau use 5.010;mendapatkannya jika Anda menjalankan yang lebih baru perl.
Robert P
Bukankah aman untuk mengasumsikan bahwa kecuali Perl 6 secara khusus disebutkan bahwa pertanyaan tersebut mengacu pada Perl 5?
wobbily_col
35

Anda dapat menggunakan -lopsi di header she-bang:

#!/usr/bin/perl -l

$text = "hello";

print $text;
print $text;

Keluaran:

hello
hello
jaypal singh
sumber
3
Sangat bagus. Lebih lanjut tentang perlopsi, termasuk apa -lyang dilakukan, di sini .
ruffin
1
Karena bersifat global, ini adalah praktik yang buruk dalam segala hal kecuali satu baris dan skrip terkecil.
Schwern
24

Jika Perl 5.10+ bukan merupakan pilihan, berikut ini adalah perkiraan cepat dan kotor. Itu tidak persis sama, karena say memiliki beberapa keajaiban ketika arg pertamanya adalah pegangan, tetapi untuk mencetak ke STDOUT:

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

say 'hello';
Eric Strom
sumber
20

Cara Anda menulis pernyataan cetak Anda tidak perlu bertele-tele. Tidak perlu memisahkan baris baru menjadi stringnya sendiri. Ini sudah cukup.

print "hello.\n";

Kesadaran ini mungkin akan membuat pengkodean Anda lebih mudah secara umum.

Selain menggunakan use feature "say"atau use 5.10.0atau use Modern::Perluntuk mendapatkan fitur bawaan say, saya akan menjadi pimp perl5i yang mengaktifkan banyak fitur Perl 5 yang hilang secara default.

Schwern
sumber
9

Mungkin Anda ingin mengubah pemisah rekaman output Anda menjadi linefeed dengan:

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

Pembaruan: jawaban saya berbicara tentang kemampuan daripada saran. Saya tidak menganggap menambahkan "\ n" di akhir baris sebagai tugas yang "mengganggu", tetapi jika seseorang benar-benar ingin menghindarinya, ini adalah salah satu cara. Jika saya harus mempertahankan sedikit kode yang menggunakan teknik ini, saya mungkin akan memfaktorkan ulangnya terlebih dahulu.

David M
sumber
6
Tidak, tolong jangan lakukan itu. Meskipun secara teknis merupakan jawaban yang benar, menggunakan variabel khusus untuk sesuatu yang sepele seperti ini merupakan beban pemeliharaan di jalan.
lihat
1
@ tsee aku setuju sepenuhnya, sebenarnya. Saat saya mengedit jawaban saya untuk menunjukkan, jawaban saya menjelaskan kemampuan, bahkan jika seseorang tidak merekomendasikannya sebagai praktik umum.
David M
Bahaya sebenarnya berasal dari kenyataan bahwa semua kode sekarang akan menambahkan baris baru, bahkan kode di modul orang lain yang tidak mengharapkannya. Bayangkan kode jaringan yang akan mengirim pesan "helo\r\n"yang sekarang terkirim "helo\r\n\n".
Chas. Owens
Tentu saja Anda selalu dapat menjadikannya lokal untuk menghindari pengaruh kode lain, tetapi tetap ingin membuat subrutin Anda terlihat sedikit lebih bersih:local $\ = "\n";
redbmk
Menggunakan flag perintah -lsangat bagus untuk baris perintah satu baris (lihat perldoc.perl.org/perlrun.html#Command-Switches ). Saya tidak akan merekomendasikannya dalam program yang lebih besar.
djd
4

Inilah yang saya temukan di https://perldoc.perl.org/perlvar.html :

$ \ Pemisah rekaman keluaran untuk operator cetak. Jika ditentukan, nilai ini dicetak setelah argumen cetak terakhir. Default-nya adalah undef.

Anda tidak bisa memanggil output_record_separator () pada pegangan, hanya sebagai metode statis. Lihat IO :: Handle.

Mnemonic: Anda menyetel $ \ daripada menambahkan "\ n" di akhir cetakan. Juga, ini seperti $ /, tapi itulah yang Anda dapatkan "kembali" dari Perl.

contoh:

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

Di Perl 6 ada, sayfungsinya

Michael Mrozek
sumber
16
Ada di 5.010 juga :-)
nc3b
1

Jika Anda terjebak dengan pra-5.10, maka solusi yang diberikan di atas tidak akan sepenuhnya mereplikasi sayfungsi tersebut. Sebagai contoh

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

Tidak akan berfungsi dengan pemanggilan seperti

say for @arr;

atau

for (@arr) {
    say;
}

... karena fungsi di atas tidak bekerja pada $_like global implisit printdan sayfungsi sebenarnya .

Untuk lebih mereplikasi perl 5.10+ sayAnda menginginkan fungsi ini

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

Yang sekarang bertindak seperti ini

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

The saybuiltin di perl6 berperilaku sedikit yang berbeda. Memanggilnya dengan say @arratau @arr.saytidak hanya akan menggabungkan item array, tetapi mencetaknya secara terpisah dengan pemisah daftar. Untuk mereplikasi ini di perl5 Anda akan melakukan ini

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

$"adalah variabel pemisah daftar global, atau jika Anda menggunakan English.pmmaka is$LIST_SEPARATOR

Sekarang akan bertindak lebih seperti perl6, seperti itu

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