Как Perl print может по умолчанию добавлять новую строку?


96

В Perl большинство моих printутверждений имеют форму

print "hello." . "\n";

Есть ли хороший способ избежать того, чтобы все надоедливые "\ n" валялись?

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


10
Если ваш ответ включает $ \, убедитесь, что в нем есть список предупреждений о настройке глобальных переменных с невидимым эффектом. Хотя это очень умно и технически отвечает на вопрос, его также очень опасно передавать неквалифицированному новичку.
Schwern

1
perldoc perlvarописывает большинство предостережений, зачем их здесь беспокоить?
Дэвид М.

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

2
Это именно та причудливая аргументация, которая привела к тому, что на моем утюге была табличка с предупреждением о том, что я не должен гладить одежду, пока я ее ношу.
Дэвид М.

8
Реальные инструменты имеют физические ограничения, которые достаточно хорошо понимают люди, прожившие свою жизнь в физическом мире. Программные инструменты не связаны такими ограничениями и нет никаких правил. Они могут делать все, что угодно, и часто ведут себя вне ожиданий, особенно для новичков, которые еще не осознали границы разумных ожиданий.
Эфир

Ответы:


101

Perl 6 имеет sayфункцию, которая автоматически добавляет \n.

Вы также можете использовать sayPerl 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

37

Вы можете использовать -lопцию в заголовке she-bang:

#!/usr/bin/perl -l

$text = "hello";

print $text;
print $text;

Выход:

hello
hello

3
Очень хорошо. Подробнее о perlвариантах, в том числе о том, что -lпроисходит, можно узнать здесь .
ruffin

2
Поскольку это глобально, это плохая практика для чего-либо, кроме однострочных и самых крошечных скриптов.
Шверн,

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.


10

Возможно, вы хотите изменить разделитель выходной записи на перевод строки с помощью:

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" в конце строк "досадной" рутиной, но если кто-то действительно хочет их избежать, это один из способов. Если бы мне пришлось поддерживать небольшой код, использующий эту технику, я бы, вероятно, быстро реорганизовал его.


6
Нет, пожалуйста, не делай этого. Хотя технически правильный ответ, использование специальной переменной для чего-то столь тривиального, как это бремя обслуживания в будущем.
tsee

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

Настоящая опасность исходит из того факта, что теперь весь код будет добавлять новые строки, даже код в модулях других людей, которые этого не ожидали. Представьте себе сетевой код, который отправил бы сообщение, "helo\r\n"которое сейчас отправляет "helo\r\n\n".
Час. Owens

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

Использование флага команды -lотлично подходит для однострочных команд командной строки (см. Perldoc.perl.org/perlrun.html#Command-Switches ). Я бы не рекомендовал его ни в одной более крупной программе.
djd

4

Вот что я нашел на https://perldoc.perl.org/perlvar.html :

$ \ Разделитель выходной записи для оператора печати. Если определено, это значение печатается после последнего аргумента print. По умолчанию 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;
}

... потому что вышеупомянутая функция не действует на неявную глобальную $_подобную 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.