Запись данных в стандартный вывод

Оператор print получает список значений и последовательно передает их (в виде строк, конечно) в стандартный вывод. Никакие дополнительные символы до, после или между элементами не выводятся. Если вы хотите, чтобы выводимые элементы завершались символом новой строки и отделялись друг от друга пробелами, это придется сделать вручную:

$name = "Larry Wall";
print "Hello there, $name, did you know that 3+4 is ", 3+4, "?\n";

Естественно, это означает, что вывод массива командой print отличается от его интерполяции:

print @array; # Вывод списка элементов
print "@array"; # Вывод строки (содержащей интерполируемый массив)

Первая команда print выводит серию элементов, один за другим, не разделяя их пробелами. Вторая команда выводит ровно один элемент, полученный в результате интерполяции @array в пустую строку, то есть содержимое @array, разделенное пробелами. Таким образом, если @array содержит qw/ fred barney betty /2, в первом случае выводится строка fredbarneybetty, а во втором – fred barney betty с разделением пробелами. Но пока вы не решили, что всегда будете использовать вторую форму, представьте, что @array содержит список входных строк, не обработанных функцией chomp.


Иначе говоря, каждая строка в списке имеет завершающий символ новой строки. Теперь первая команда print выведет имена fred, barney и betty в трех разных строках. Но вывод второй команды будет выглядеть так:

fred
barney
betty

Видите, откуда взялись лишние пробелы? Perl интерполирует массив и вставляет пробелы между его элементами. Таким образом, выводится первый элемент массива (fred и символ новой строки), затем пробел, потом следующий элемент массива (barney и символ новой строки), затем пробел и последний элемент массива (betty и символ новой строки). В результате все строки, кроме первой, выводятся с дополнительным отступом. Каждую пару недель в списках рассылки или на форумах неизменно появляются сообщения с темой, которая выглядит примерно так: Perl выводит лишние пробелы во всех строках, кроме первой. Даже не читая сообщение, можно сразу догадаться, что массив с завершающими символами новой строки был интерполирован в кавычках. Так оно всегда и оказывается. В общем случае, если вводимые строки завершаются символом новой строки, их следует просто вывести командой

print @array;

Если же завершающие символы новой строки отсутствуют, они обычно добавляются вручную:

print "@array\n";

Итак, при использовании print с кавычками (обычно) в конец строки добавляется \n.


Надеемся, вы запомнили, чем различаются эти две формы print. Вывод программы обычно буферизуется. Иначе говоря, вместо немедленной отправки каждого фрагмента выводимые данные сохраняются в буфере, пока их не наберется достаточно для выполнения операции. Скажем, при сохранении вывода на диске позиционирование пишущего механизма выполняется (относительно) медленно, поэтому было бы неэффективно выполнять эту операцию при каждой записи одногодвух символов в файл. Как правило, вывод накапливается в промежуточном буфере, а потом сбрасывается (то есть записывается на диск или в другой приемник) только при заполнении буфера или завершении вывода по другим причинам (например, выхода из программы). Обычно буферизация предпочтительнее прямого вывода. Но если вы (или программа) с нетерпением ожидаете вывода, возможно, вы согласитесь на некоторое снижение быстродействия и предпочтете, чтобы содержимое буфера сбрасывалось при каждом выводе. За дополнительной информацией об управлении буферизацией обращайтесь к man-страницам Perl. Поскольку print получает список строк для вывода, аргументы функции обрабатываются в списковом контексте. А раз оператор <> (как особая разновидность оператора построчного ввода) возвращает список строк в списочном контексте, они могут использоваться совместно:

print <>; # Реализация 'cat'
print sort <>; # Реализация 'sort'

Откровенно говоря, стандартные команды UNIX cat и sort обладают дополнительной функциональностью, отсутствующей в этих заменителях.


Но уж превзойти их по компактности точно не удастся! Теперь вы можете переписать все свои стандартные утилиты UNIX на Perl и легко портировать их на любой компьютер с установленным языком Perl независимо от того, относится ли система к семейству UNIX или нет. И вы можете быть уверены, что на разнотипных компьютерах ваши программы будут работать одинаково. Но есть еще одно, менее очевидное обстоятельство: print имеет необязательные круглые скобки, которые иногда приводят к недоразумениям. Вспомните, что круглые скобки в Perl всегда можно опустить, если только это не изменит смысла выражения. Значит, следующие две команды должны привести к одному результату:

print("Hello, world!\n");
print "Hello, world!\n";

Пока все хорошо. Но в Perl есть и другое правило, которое гласит: если вызов print выглядит как вызов функции, это и есть вызов функции. Правило простое, но как понимать «выглядит как вызов функции»? Вызов функции состоит из ее имени, непосредственно1 за которым следуют круглые скобки с аргументами функции:

print (2+3);

Команда выглядит как вызов функции, а следовательно, является вызовом функции. Она выводит 5, но затем, как и любая другая функция, возвращает значение.


Функция print возвращает true или false в зависимости от того, успешно ли была выполнена печать. Она почти всегда выполняется успешно (разве что если произойдет ошибка ввода/вывода), поэтому переменной $result в следующей команде обычно присваивается значение:

$result = print("hello world!\n");

А если результат будет использоваться как-то иначе? Допустим, вы решили умножить возвращаемое значение на 4:

print (2+3)*4; # Сюрприз!

Встретив эту строку, Perl выводит 5, как и положено. Затем он берет возвращаемое значение print, равное 1, умножает его на 4 и… отбрасывает, удивляясь, почему вы ничего не сделали с вычисленным произведением. Если кто-нибудь в этот момент заглянет вам через плечо, он скажет: «Да Perl не умеет считать! Здесь должно получиться 20, а не 5!» В этом кроется проблема необязательных круглых скобок; иногда мы, люди, забываем, к чему они относятся. При отсутствии круглых скобок print является списочным оператором, который выводит все элементы из последующего списка; обычно программист рассчитывает именно на такое поведение. Но если сразу же после print следует открывающая круглая скобка, print становится вызовом функции и выводит только то, что стоит в круглых скобках.


При наличии круглых скобок для Perl эта команда равносильна следующей:

( print (2+3) ) * 4; # Сюрприз!

К счастью, Perl почти всегда помогает находить подобные ситуации, если вы включите режим предупреждений. Поэтому используйте ключ –w или директиву use warnings, по крайней мере, во время разработки и отладки программы. Вообще говоря, это правило – «Если что-то выглядит как вызов функции, то оно и является вызовом функции» – применимо ко всем списочным функциям1 Perl, не только к print. Просто при вызове print вы заметите его с наибольшей вероятностью. Если за print (или именем другой функции) следует открывающая круглая скобка, проследите за тем, чтобы парная круглая скобка находилась после всех аргументов этой функции.

Оцените статью: (0 голосов)
0 5 0

Статьи из раздела Perl на эту тему:
Аргументы вызова
Ввод данных оператором <>
Вывод функцией say
Закрытие файлового дескриптора
Изменение файлового дескриптора вывода по умолчанию

Вернуться в раздел: Perl / 4. Ввод и вывод