การพิมพ์ของ Perl จะเพิ่มขึ้นบรรทัดใหม่ตามค่าเริ่มต้นได้อย่างไร


96

ใน Perl ข้อความส่วนใหญ่ของฉันprintอยู่ในรูปแบบ

print "hello." . "\n";

มีวิธีที่ดีในการหลีกเลี่ยงการโกหก "\ n" ที่น่ารำคาญหรือไม่?

ฉันรู้ว่าฉันสามารถสร้างฟังก์ชันใหม่เช่นmyprintที่ต่อท้ายโดยอัตโนมัติ \ n แต่จะดีถ้าฉันสามารถแทนที่ไฟล์print.


10
หากคำตอบของคุณมี $ \ โปรดตรวจสอบให้แน่ใจว่ามีรายการคำเตือนเกี่ยวกับการตั้งค่าตัวแปรส่วนกลางที่มีเอฟเฟกต์ที่มองไม่เห็น ในขณะที่มันฉลาดมากและตอบคำถามในทางเทคนิค แต่ก็อันตรายมากที่จะส่งมอบให้กับมือใหม่อย่างไม่มีเงื่อนไข
Schwern

1
perldoc perlvarอธิบายคำเตือนส่วนใหญ่ทำไมถึงเชื่อที่นี่?
David M

5
@David เพราะแฮ็กเกอร์แบบสุ่มบางคนจะค้นหาคำตอบที่นี่แทนที่จะเป็น perldoc พึงพอใจกับพวกเขาและไม่รู้เกี่ยวกับข้อควรระวัง!
P Shved

2
นั่นเป็นเหตุผลแปลก ๆ ที่ส่งผลให้เตารีดของฉันมีป้ายเตือนว่าฉันไม่ควรรีดเสื้อผ้าในขณะที่สวมใส่
David M

8
เครื่องมือในชีวิตจริงมีข้อ จำกัด ทางกายภาพที่เข้าใจได้ดีพอสมควรสำหรับผู้ที่ใช้ชีวิตในโลกทางกายภาพ เครื่องมือซอฟต์แวร์ไม่มีข้อ จำกัด ดังกล่าวและไม่มีกฎเกณฑ์ใด ๆ พวกเขาสามารถทำอะไรก็ได้และมักประพฤติตัวนอกความคาดหวังโดยเฉพาะอย่างยิ่งสำหรับผู้เริ่มต้นที่ยังไม่ได้เรียนรู้ขอบเขตของความคาดหวังที่สมเหตุสมผล
Ether

คำตอบ:


101

Perl 6 มีฟังก์ชั่นที่จะผนวกsay\n

คุณยังสามารถใช้sayใน Perl 5.10 หรือ 5.12 ได้หากคุณเพิ่ม

use feature qw(say);

ไปยังจุดเริ่มต้นของโปรแกรมของคุณ หรือคุณสามารถใช้Modern :: Perlเพื่อรับสิ่งนี้และคุณสมบัติอื่น ๆ

ดูคุณสมบัติ perldocสำหรับรายละเอียดเพิ่มเติม


7
ในความเป็นจริงสิ่งที่คุณต้องทำก็คือuse 5.012;หรือuse 5.010;เพื่อให้ได้มาซึ่งถ้าคุณใช้งานperls ที่ใหม่กว่า
Robert P

ไม่ปลอดภัยที่จะสันนิษฐานว่าเว้นแต่จะมีการกล่าวถึง Perl 6 โดยเฉพาะว่าคำถามอ้างถึง Perl 5
wobbily_col

38

คุณสามารถใช้-lตัวเลือกในส่วนหัวของเธอ:

#!/usr/bin/perl -l

$text = "hello";

print $text;
print $text;

เอาท์พุต:

hello
hello

3
ดีมาก. เพิ่มเติมเกี่ยวกับperlตัวเลือกรวมถึงสิ่งที่-lจะทำที่นี่
ruffin

2
เนื่องจากเป็นเรื่องทั่วโลกนี่จึงเป็นแนวทางปฏิบัติที่ไม่ดีในทุกอย่างยกเว้นเพียงเส้นเดียวและสคริปต์ที่น้อยที่สุด
Schwern

24

หาก Perl 5.10+ ไม่ใช่ตัวเลือกนี่เป็นวิธีการประมาณที่รวดเร็วและสกปรก มันไม่เหมือนกันทุกประการเนื่องจาก say มีเวทมนตร์เมื่อ arg แรกเป็นที่จับ แต่สำหรับการพิมพ์ไปยัง STDOUT:

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

say 'hello';

20

วิธีที่คุณเขียนใบแจ้งยอดการพิมพ์ของคุณเป็นแบบละเอียดโดยไม่จำเป็น ไม่จำเป็นต้องแยกขึ้นบรรทัดใหม่เป็นสตริงของตัวเอง เท่านี้ก็เพียงพอแล้ว

print "hello.\n";

การตระหนักรู้นี้อาจทำให้การเข้ารหัสของคุณง่ายขึ้นโดยทั่วไป

นอกเหนือจากการใช้use feature "say"หรือuse 5.10.0หรือuse Modern::Perlเพื่อรับsayคุณสมบัติในตัวฉันจะแมงดาperl5iซึ่งจะเปิดใช้คุณสมบัติ Perl 5 ที่หายไปอย่างสมเหตุสมผลตามค่าเริ่มต้น


10

บางทีคุณอาจต้องการเปลี่ยนตัวคั่นเร็กคอร์ดเอาต์พุตของคุณเป็น linefeed ด้วย:

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

อัปเดต: คำตอบของฉันพูดถึงความสามารถมากกว่าความเหมาะสม ฉันไม่ถือว่าการเพิ่ม "\ n" ที่ท้ายบรรทัดจะเป็นงานที่ "น่ารำคาญ" แต่ถ้ามีคนต้องการหลีกเลี่ยงจริงๆนี่เป็นวิธีหนึ่ง ถ้าฉันต้องรักษาโค้ดที่ใช้เทคนิคนี้ฉันอาจจะ refactor มันทันที


6
ไม่โปรดอย่าทำอย่างนั้น แม้ว่าในทางเทคนิคจะเป็นคำตอบที่ถูกต้อง แต่การใช้ตัวแปรพิเศษสำหรับสิ่งที่ไม่สำคัญเนื่องจากเป็นภาระการบำรุงรักษาตามท้องถนน
tsee

1
@tsee ฉันเห็นด้วยอย่างสมบูรณ์จริง ขณะที่ฉันแก้ไขคำตอบเพื่อระบุคำตอบของฉันจะอธิบายถึงความสามารถแม้ว่าจะไม่มีใครแนะนำให้เป็นแนวทางปฏิบัติทั่วไปก็ตาม
David M

อันตรายที่แท้จริงมาจากความจริงที่ว่าตอนนี้โค้ดทั้งหมดจะเพิ่มขึ้นบรรทัดใหม่แม้กระทั่งโค้ดในโมดูลของคนอื่นที่ไม่คาดคิด ลองนึกภาพรหัสระบบเครือข่ายที่จะได้ส่งข้อความว่าตอนนี้ส่ง"helo\r\n" "helo\r\n\n"
Chas. Owens

แน่นอนว่าคุณสามารถทำให้เป็นแบบโลคัลได้เสมอเพื่อหลีกเลี่ยงการส่งผลกระทบต่อโค้ดอื่น ๆ แต่ยังคงต้องการทำให้รูทีนย่อยของคุณดูสะอาดขึ้นเล็กน้อย:local $\ = "\n";
redbmk

การใช้แฟล็กคำสั่ง-lเหมาะสำหรับบรรทัดคำสั่ง one-liners (ดูperldoc.perl.org/perlrun.html#Command-Switches ) ฉันจะไม่แนะนำในโปรแกรมที่ใหญ่กว่านี้
djd

4

นี่คือสิ่งที่ฉันพบที่https://perldoc.perl.org/perlvar.html :

$ \ ตัวคั่นเร็กคอร์ดเอาต์พุตสำหรับตัวดำเนินการพิมพ์ หากกำหนดค่านี้จะถูกพิมพ์หลังจากอาร์กิวเมนต์สุดท้ายของการพิมพ์ ค่าเริ่มต้นคือ undef

คุณไม่สามารถเรียก output_record_separator () บนแฮนเดิลได้ แต่เป็นวิธีการแบบคงที่เท่านั้น ดู IO :: Handle

ช่วยในการจำ: คุณตั้งค่า $ \ แทนการเพิ่ม "\ n" ที่ส่วนท้ายของการพิมพ์ นอกจากนี้มันก็เหมือนกับ $ / แต่เป็นสิ่งที่คุณ "กลับมา" จาก Perl

ตัวอย่าง:

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


1

หากคุณติดอยู่กับพรี 5.10 โซลูชันที่ให้ไว้ข้างต้นจะไม่สามารถจำลองsayฟังก์ชันได้ทั้งหมด ตัวอย่างเช่น

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

จะไม่ทำงานกับการเรียกใช้เช่น

say for @arr;

หรือ

for (@arr) {
    say;
}

... เนื่องจากฟังก์ชันข้างต้นไม่ได้ทำหน้าที่เกี่ยวกับ global $_like printและsayฟังก์ชันจริงโดยนัย

หากต้องการจำลอง perl 5.10+ อย่างใกล้ชิดยิ่งขึ้นsayคุณต้องการฟังก์ชันนี้

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

ซึ่งตอนนี้ทำหน้าที่แบบนี้

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

saybuiltin ใน Perl6 ทำงานเล็ก ๆ น้อย ๆ ที่แตกต่างกัน การเรียกใช้โดยมีsay @arrหรือ@arr.sayจะไม่เพียงแค่เชื่อมต่อรายการอาร์เรย์ แต่จะพิมพ์แยกออกจากกันด้วยตัวคั่นรายการ ในการจำลองสิ่งนี้ใน perl5 คุณต้องทำสิ่งนี้

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

$"คือตัวแปรตัวคั่นรายการส่วนกลางหรือถ้าคุณใช้English.pmอยู่ก็คือ$LIST_SEPARATOR

ตอนนี้มันจะทำหน้าที่เหมือน perl6 มากขึ้นเช่นนั้น

say @arr;
# OUTPUT
# alpha beta gamma
#
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.