Как 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.