Як друк Perl може додати новий рядок за замовчуванням?


95

У Perl більшість моїх printзаяв приймають форму

print "hello." . "\n";

Чи є приємний спосіб уникнути того, щоб усі дотепні "\ n" лежали навколо?

Я знаю, що міг би зробити нову функцію, таку, myprintяка автоматично додається \ n, але було б добре, якби я міг переосмислити існуючу print.


10
Якщо Ваша відповідь включає $ \, будь ласка, переконайтеся, що вона містить список застережень щодо встановлення глобальних змінних з невидимим ефектом. Незважаючи на те, що дуже розумний і технічно відповідає на питання, його також дуже небезпечно передавати новачкові некваліфіковано.
Schwern

1
perldoc perlvarописує більшість застережень, навіщо їх тут робити?
Девід М

5
@David, тому що якийсь випадковий хакер перегляне тут відповіді замість perldoc, задовольниться ними і навіть не дізнається про застереження!
П Швед

2
Це саме такі химерні міркування, що призвели до того, що моя праска мала попереджувальну етикетку, що я не повинен прасувати одяг, поки я їх ношу.
Девід М

8
Інструменти реального життя мають фізичні обмеження, які досить добре розуміють люди, які прожили своє життя у фізичному світі. Програмні засоби не обмежуються такими обмеженнями, і немає ніяких правил. Вони можуть робити все, що завгодно, і часто поводяться поза сподіваннями, особливо для початківців, які ще не вивчили межі розумних очікувань.
Ефір

Відповіді:


99

Perl 6 має sayфункцію, яка автоматично додається \n.

Ви також можете використовувати sayв Perl 5.10 або 5.12, якщо додати

use feature qw(say);

до початку вашої програми. Або ви можете використовувати Modern :: Perl, щоб отримати цю та інші функції.

Докладніше див. У функції Perldoc .


7
Насправді все, що вам потрібно зробити, - це use 5.012;або use 5.010;отримати його, якщо ви працюєте з тими новішими perl.
Роберт П

Хіба не можна припустити, що якщо Perl 6 конкретно не згадується, що питання стосується Perl 5?
wobbily_col

35

Ви можете використовувати -lпараметр у заголовку she-bang:

#!/usr/bin/perl -l

$text = "hello";

print $text;
print $text;

Вихід:

hello
hello

3
Дуже хороша. Більше про perlваріанти, зокрема про те, що -lробиться, тут .
ruffin

1
Оскільки це глобально, це погана практика в чому-небудь, крім однолінійки та найменшого сценарію.
Шверн

24

Якщо Perl 5.10+ не є варіантом, ось швидке та брудне наближення. Це не зовсім те саме, оскільки say має певну магію, коли його перший аргумент - це ручка, але для друку в 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 функцій за замовчуванням.


9

Можливо, ви хочете змінити роздільник вихідних записів на лінійку:

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" в кінці рядків є "прискіпливою" рутиною, але якщо хтось дійсно хоче їх уникнути, це один із способів. Якби мені довелося підтримувати трохи коду, який використовує цю техніку, я, мабуть, переробляв його на pronto.


6
Ні, будь ласка, не робіть цього. Хоча технічно правильна відповідь, використання спеціальної змінної для чогось такого тривіального, як це є тягарем технічного обслуговування в дорозі.
tsee

1
@tsee Я згоден повністю, насправді. Коли я редагував свою відповідь, щоб вказати, моя відповідь описує можливість, навіть якщо хтось не рекомендував би її як загальну практику.
Девід М

Справжня небезпека походить від того, що весь код тепер буде додавати нові рядки, навіть код в модулях інших людей, які цього не очікували. Уявіть собі мережевий код, який послав би повідомлення, "helo\r\n"яке зараз надсилає "helo\r\n\n".
Час. Оуенс

Звичайно, ви завжди можете зробити його локальним, щоб не впливати на інший код, але все ж хочете, щоб ваша підпрограма виглядала трохи чистішою:local $\ = "\n";
redbmk

Використання прапора команди -lвідмінно підходить для одноклассників командного рядка (див. Perldoc.perl.org/perlrun.html#Command-Switches ). Я б не рекомендував це в будь-якій більшій програмі.
дед

4

Ось що я знайшов на https://perldoc.perl.org/perlvar.html :

$ \ Розділювач виводу запису для оператора друку. Якщо визначено, це значення друкується після останнього аргументу друку. За замовчуванням значення undef.

Ви не можете викликати output_record_separator () на дескрипторі, лише як статичний метод. Див. IO :: Ручка.

Мнемоніка: ви встановлюєте $ \ замість того, щоб додавати "\ 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;
}

... тому що вищенаведена функція не діє на загальноприйняті глобальні $_подібні 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
#

sayВбудований в 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
#
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.