Perl вывести содержимое файла

Обновлено: 02.07.2024

О том, что такое файл писать я надеюсь ненужно, но думаю нужно подумать над тем, что с ними можно делать, как видно из заголовка статьи, на Perl. Ну, приступим .

В этой статье обсудим:

Что такое файловые манипуляторы, и с чем их едят

Доступ к файлам осуществляется с помощью файловых манипуляторов, которые представляют собой так сказать синоним файла. Они не являются переменными, а поэтому их нельзя непосредственно присваивать другим переменным или передавать в функции (для этого нужно, что называется, пойти другим путем).

Есть и стандартные Перловские файловые манипуляторы. Они называются STDIN (стандартный ввод), STDOUT (стандартный вывод) и STDERR (стандартный поток ошибок). Например параметры скрипту из формы передаются именно через STDIN (при условии использования метода POST).

Если понадобится создать копию файлового манипулятора (не файла, а только манипулятора по которому осуществляется доступ к файлу), то можно воспользоваться функцией open (о ней подробнее поговорим позже).

О присваивании переменным файловых манипуляторов:

И под конец скажу, что файловые манипуляторы в Perl используются не только для связи с, собственно, файлом. Они могут быть связаны с каким-нибудь процессом, сокетом и т.д. Но это не входит в тематику статьи.

Манипуляции с файлом

Открытие файла осуществляется функцией open.

Разберемся. У функции три параметра: FFF - название файлового манипулятора (его задаете вы), режим доступа ">" и "file.txt" - имя нужного вам файла. Есть три основных режима: ">" - запись,"<"- чтение, ">>"- добавление в файл.

Есть еще функция sysopen. Работа с ней не на много сложнее, чем с open, зато с ее помощью вы сможете более детально "сказать" системе о ваших намерениях (то есть то, что вы хотите сделать с файлом).

В sysopen три обязательных параметра и один необязательный.

FH - собственно, файловый манипулятор, $name - имя файла в чистом виде (без ">" и др.). В $flags помещаем число, полученное объединением нижеописанных констант через OR ( | ):

O_RDONLY Только для чтения
O_WRONLY Только для записи
O_RDWR Для чтения и для записи
O_CREAT Если файла нет, создать!
O_APPEND Открытие в режиме присоединения
O_TRUNC Очищаем содержимое при открытии

Это, конечно, не полный перечень, но здесь перечислены самые необходимые и часто используемые константы.

И наконец $param. Этот параметр задает маску доступа к файлу и записывается в восьмеричной системе. Обычно используется значение 0666 (значение по умолчанию, то есть если $param опущен), или 0777. Первое значение используется для обычных файлов, второе же для каталогов и исполняемых файлов.

Пример открытия файла для записи (если не найден - создается):

Запись в файл делаем функцией print.

Здесь FFF - имя файлового манипулятора, а строка в кавычках - текст, который мы хотим записать в файл, ассоциированный с FFF.

Если до попытки открытия файла не существовало, то функция open его создаст, а если файл был, и он был не пустой, то после вышеуказанной функции print, в нем ничего не останется от предыдущей информации, а записана будет та ерунда, которую я там вписал.

Как уже было сказано, существуют три стандартных файловых манипулятора, и при опущенном файловом манипуляторе функция print осуществит вывод в STDOUT (то же относится к функциям printf и write). Чтобы изменить направление вывода в Perl предусмотрена функция select (правда не только для этого). Пример:

Закрываем файл функцией close.

Принцип убирать за собой прививается всем с детства. Давайте не забывать об этом и в программировании, хотя при завершении процесса, в котором был открыт данный файл, файл закрывается автоматически.

Во-первых для чего? А для того, что если несколько процессов хотят одновременно заполучить доступ к файлу, причем на запись, причем еще и хотят туда что-то писать (кошмар), то представьте, что оказалось бы, если не этот чудный механизм блокировки. Он позволяет, грубо говоря, ставить процессы в очередь. Делаем так:

О функциях open и close уже говорили, а на flock остановимся немного подробнее. Она получает два параметра - файловый манипулятор и, образно говоря, категорию блокировки.

Про снятие блокировки: блокировка автоматически снимается при завершении процесса, вызванного текущим скриптом, либо при закрытии файлового манипулятора, который "привязан" к заблокированному файлу. Если вы снимаете блокировку вручную, будьте аккуратны - вы даете возможность другому процессу делать с (ВНИМАНИЕ!) не закрытым вами файлом все что ему угодно! Последствия могут быть, мягко говоря, неприятные, а грубо говоря - непредсказуемые (для вас непредсказуемые).

Работа со строками в файле

Так как именно те файлы, которые содержат строковую информацию составляют наибольший интерес для, собственно, человека, то и речь сейчас пойдет именно о них.

Для чтения строк из файла используется файловый манипулятор "поставленный" в <>.

Если не указано иначе, то внутри такого цикла используется стандартная переменная "$_", а номер строки записывается в "$.". Так как конец строки обозначается спецсимволом, например "\n", для получения самой строки (без эдакого "хвоста") нужно ее усечь функцией chomp.

Можно прочитать строки в массив:

Для передвижения по файлу используются функции tell и seek.

Функция tell принимает в качестве параметра файловый манипулятор, а seek берет три параметра. Первый - файловый манипулятор, второй - смещение в байтах, третий - направление смещение. Есть три направления смещения: 0 - от начала файла, 1 - от текущей позиции, 2 - с конца файла.

Нельзя сказать, что это все, что нам предлагает Perl для работы с файлами. Будем надеяться, что у меня будет время на то, чтобы написать о том, как работать с каталогами, тонкости при работе с бинарными файлами, объектно-ориентированный подход к управлению файлами и их содержимым.

Если вы пропустили предыдущие три части, я бы советовал начать чтение с начала . В принципе, эту серию уроков можно читать в произвольном порядке и во всем разобраться, но зачем усложнять себе жизнь?

В отличие от предыдущих уроков, которые можно было читать практически без подготовки, сегодня от вас потребуется понимание того, что такое стандартные потоки ввода и вывода, файловый дескриптор, права доступа к файлам и тп. К сожалению, эти вопросы выходят за рамки статьи, так что вам предстоит разобраться в них самостоятельно. К счастью, с этим вам поможет практически любая книжка по основам ОС семейства UNIX. Да и в сети соответствующих статей должно быть в изобилии.

Ввод и вывод

Как всегда, давайте начнем с примера:

Функция chomp проверяет, находится ли в конце строки-аргумента символ новой строки (\n) и если он присутствует, отсекает его. Если такого символа нет, строка остается без изменений.

print STDOUT "Вывод строки в стандартный поток вывода \n " ;
print STDERR "Вывод строки в стандартный поток ошибок \n " ;

Только что мы рассмотрели открытие файла на чтение. Чтобы открыть файл на запись, нужно перед его именем указать > или >>:

В заключение к этому разделу хотелось бы рассказать об интересной особенности оператора <>. Дело в том, что он может использоваться без указания файлового дескриптора:

В этом случае, если скрипт был вызван без аргументов, оператор будет производить чтение из STDIN. В противном случае все аргументы будут рассматриваться, как имена файлов. Чтение будет производиться по очереди из каждого файла. Можно сказать, что этот скрипт представляет собой аналог утилиты cat.

Работа с каталогами

Тут все настолько просто, что даже комментировать не хочется. Давайте лучше сразу перейдем к более интересному примеру:

Существует и более короткая запись:

А еще можно так:

Использовать функцию glob лучше в тех случаях, когда в выражение нужно подставить переменную.

Другие операции над файлами и каталогами

Также в Perl имеется несколько довольно полезных операторов:

Заключение

Дополнение. См также заметки, посвященные регулярным выражениям, объектно-ориентированному программированию в Perl и заливке модулей на CPAN. Можете считать их дополнениями к этой серии уроков.

Открывается файл при помощи встроенной процедуры open . Процедура получает три параметра: переменную для создаваемого дескриптора, строку, обозначающую режим открытия (чтение, запись или что-то ещё), и, наконец, имя файла:

Мы обожаем совмещать объявление переменной для дескриптора с вызовом процедуры open :

Значение '<' , переданное как второй параметр, символизирует чтение. Знак «меньше», повернувшийся спиной к имени файла, как бы намекает нам, что готовится извлечение информации из файла. Угадайте, как открыть файл для записи? Конечно же так:

В примерах использования процедуры open указывалось относительное имя файла — по отношению к директории, являющейся для данной программы текущей. Сразу после запуска программы это та директория, из которой запущена программа. Но текущая директория может быть изменена процедурой chdir :

Нет никаких противопоказаний к тому, чтобы задавать при открытии абсолютное имя файла:

В некоторых операционных системах, в полных именах файлов применяется другой разделитель директорий. Например, в Microsoft DOS и Microsoft Windows вместо слэша / применяется разделитель бэкслэш \ . Тем не менее, задавая полное имя в программе на Perl при открытии, следует использовать слэш: '/c:/dos/autoexec.bat' .

Закрытие

Интуиция подсказывает нам, что всё, что открывается, должно быть рано или поздно закрыто. Это верно и для файлов. Любой сценарий ввода/вывода устроен одинаково: открытие, собственно ввод или вывод, и, наконец, закрытие.

Закрытие файла освобождает ресурсы операционной системы, занятые при открытии, и гарантирует, что данные, записанные в файл, дойдут по назначению. После закрытия переменная-дескриптор теряет актуальность и не может быть использована для ввода/вывода.

Для закрытия файлов служит встроенная процедура close :

Обработка ошибок при открытии и закрытии файлов

Не стоит ожидать, что открытие файла всегда будет успешным. Есть много причин, которые могут помешать. Среди них:

  • отсутствие нужного файла;
  • отсутствие прав на чтение или запись;
  • неполадки с носителем: испорченный диск или флешка, перебои с сетью в случае сетевых файлов.

Обратите внимание на специальную переменную $! . В случае возникновения ошибки в эту переменную автоматически помещается текст, объясняющий причину ошибки, например, Нет такого файла или каталога или Отказано в доступе или что-то ещё. Текст в $! , в зависимости от системных настроек, может быть на другом языке.

Гораздо изящней выглядит следующая идиома:

В этом логическом выражении два операнда. Если первый (то, что возвращает open ) принимает истинное значение, то в вычислении второго нет нужды, так как всё выражение уже заведомо истинно. Если же open возвратит ложное значение, то значение всего выражения определяется по второму операнду, который в этом случае должен быть вычислен. Для вычисления будет вызвана процедура die со всеми вытекающими последствиями.

Конечно, программа не обязана завершать работу при неудачном открытии файла. Например, если предполагается обработка нескольких файлов, можно просто перейти к следующему, сообщив об ошибке при помощи процедуры warn :

Чтение

Имеется два способа чтения из дескриптора: побайтное/посимвольное и построчное.

Побайтное и посимвольное чтение

При побайтном/посимвольном чтении файла программа запрашивает у открытого дескриптора очередную порцию данных нужного размера и предоставляет скалярную переменную для запрошенных данных. Для чтения служит встроенная процедура read :

В этом примере предполагается, что $file — дескриптор файла, открытого для чтения, и что размер очередной запрошенной дозы информации — шестнадцать байт. Эти шестнадцать байт отправляются в переменную $buffer . После выполнения такой команды дескриптор выражает готовность читать дальше.

Можно представлять себе файл, открытый для чтения, как последовательность байтов. Воображаемый указатель отделяет уже прочитанную часть последовательности от ещё непрочитанной. Операция чтения приводит, помимо прочего, к сдвигу указателя к концу файла. За счёт этого следующая команда чтения получит доступ к новой порции данных. Дескриптор файла хранит в себе разнообразную информацию об открытом файле, и, в том числе, этот указатель — номер первого непрочитанного байта. Сразу после открытия указатель равен нулю.

Что же будет, если запросить при чтении больше байт, чем размер непрочитанной части файла? Ничего страшного, компьютер не сломается. Просто в переменную-буфер отправится меньше байт, чем было запрошено. Контролировать это явление удобно, пользуясь возвращаемым значением процедуры read — это количество байт, которое удалось прочесть. Широко распространена при программировании на Perl такая идиома:

Здесь значение, возвращённое из read , используется в качестве условия цикла. Рано или поздно файл будет прочитан до конца, и следующий вызов read возвратит ноль (ложное значение). Это прервёт цикл, что нам, собственно, и нужно.

Построчное чтение

В отличие от побайтного/посимвольного чтения, когда запрашивается заданное количество байтов или символов, при построчном чтении размер прочитанного заранее не оговаривается. Вместо этого считывается строка — последовательность байтов или символов вплоть до символа или символов, обозначающих конец строки.

Построчное чтение осуществляется оператором <…> . Код < $file > приводит к считыванию очередной строки из дескриптора $file в переменную по умолчанию $_ .

Для последовательной обработки всех строк файла удобно использовать цикл while . Например, программа, печатающая содержимое файла на экран, строка за строкой, могла бы выглядеть так:

Здесь читатель справедливо задаётся вопросом: что именно печатает процедура print в теле цикла? Переменную по умолчанию, конечно. Можно было бы написать print $_ , но вряд ли это добавит ясности.

Другой пример. В уже открытом файле записаны числа, по одному в строке. Требуется вывести на экран их сумму.

Команда chomp необходима вот по какой причине. Оператор <…> вместе со строкой считывает и завершающий строку символ, который создаст проблему, если считанная строка впоследствии будет участвовать в арифметическом выражении. Встроенная процедура chomp удаляет этот символ, если строка заканчивается им. Если же последний символ другой, процедура ничего не делает. такая предосторожность нужна на тот случай, если, к несчастью, файл не заканчивается символом конца строки. Тогда и последняя прочитанная из файла строка закончится чем-то другим. Имеется также процедура chop , которая удаляет и возвращает последний символ строки независимо от того, какой он. Обе процедуры, chop и chomp , работают со строкой, переданной как параметр, но в отсутствие параметра — с переменной $_ .

Не следует думать, что с оператором построчного чтения мы обречены на использование переменной $_ . Если требуется читать в другую переменную, используем присваивание:

Самое время сообщить об одной особенности оператора построчного чтения. Его смысл немного меняется, если оператор поместить в списочный контекст, то есть туда, где должен быть список. Например, если присвоить массиву:

В этом случае все строки, прочитанный из файла, заполнят массив. Ещё можно организовать переборный цикл:

Этот код, как и приведённый выше цикл while , печатает строки файла на экран. К тому же результату приведёт код

(здесь пропущено слово for ). Но мы не рекомендуем такой подход, поскольку здесь сначала прочитываются все строки из файла, а затем передаются как список параметров в процедуру print . При этом все строки без всякой необходимости занимают память, а при большом файле объём памяти может быть очень велик.

Вообще, построчное чтение может создать похожую проблему, если в файле имеются очень длинные строки. И хотя это не характерно для текстовых файлов (например, созданных в текстовом редакторе), следует принимать это обстоятельство во внимание.

Запись

При открытии файла для чтения предполагается, что файл существует, в противном случае открытие приводит к ошибке. Если файл открывается для записи, требовать существования файла уже не стоит: отсутствующий файл создаётся пустым. Если же файл существовал, всё его содержимое уничтожается, и мы снова получаем пустой файл.

Для записи в дескриптор применяется давно знакомая нам процедура print , но не совсем так, как мы привыкли:

Здесь содержимое строки $string записывается в открытый дескриптор $file . Обратите особое внимание на отсутствие запятой после первого параметра $file . С запятой смысл команды будет другим: в дескриптор ничего не запишется, а вместо этого программа выведет на экран строковое представление значений обеих переменных $file и $string :

(шестнадцатеричное число в скобках, скорее всего, будет другим, ну и вместо слова Привет! может оказаться другой текст). Число это нам ни о чём не говорит, как и загадочное слово GLOB вместе со скобками. Итак, если все параметры процедуры print разделены запятыми, все они печатаются на экран. Если после первого параметра нет запятой, этот параметр должен быть дескриптором, открытым для записи, а остальные параметры записываются в него:

Можно все параметры после дескриптора заключить в скобки:

Один из видных специалистов по языку Perl рекомендует заключать дескриптор в фигурные скобки, чтобы зрительно отделить его от остальных параметров:

Форматированный вывод

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

Таким способом можно вставлять в шаблон и строки, и числа. Что касается чисел, в каких-то ситуациях может потребоваться их особое форматирование. Числа перед включением в шаблон может потребоваться округлить до нужного количества десятичных цифр после точки, дополнить слева нужным количеством нулей или пробелов, чтобы число хорошо смотрелось в таблице. Может потребоваться вставить число в двоичном или шестнадцатеричном формате.

Теперь подробнее о форматных строках и форматных метках.

Если вставляемое число нужно вывести как целое (то есть с отбрасыванием дробной части), метка имеет вид %d :

Вот так можно выводить целые числа с выравниванием:

Для выравнивания числа можно дополнять слева не пробелами, а нулями:

Шестнадцатеричный формат с дополнением нулями до трёх цифр:

Двоичный формат с дополнением пробелами до четырёх знаков:

Округление с двумя цифрами после десятичной точки:

Приведённые примеры не охватывают все возможные форматы, понятные процедурам printf и sprintf , но для наших задач будет достаточно и этого.

Использование знака процента как признака метки лишает нас возможности использовать его в форматной строке как таковой. Эта трудность не новая для нас, и разрешается она уже хорошо знакомым способом. Комбинация из двух знаков процента означает одиночный знак процента (подобно тому, как \\ внутри "" -строк означает один бэкслэш):

Точно так же, как и print , процедура printf может осуществлять вывод не только на экран, но и дескриптор файла, открытого для записи или для добавления:

Ни одна программа не может функционировать сама по себе, не получая и не посылая информацию во внешнюю среду. Perl предоставляет несколько способов получения программой данных извне и вывода информации из выполняющегося сценария. В процессе функционирования программы может потребоваться выполнить некоторую команду операционной системы и проанализировать результаты ее выполнения, прочитать данные из внешнего файла или группы файлов, записать результаты вычислений во внешний файл или отобразить их на экране монитора — все эти действия реализуются разнообразными операциями и функциями языка Perl.

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

Для чтения из файла используется операция "ромб" о, которой в качестве операнда передается дескриптор файла. В этой главе мы не будем обсуждать ввод из файла через его дескриптор, отнеся рассмотрение этого вопроса в следующую главу, полностью посвященную работе с файлами. Здесь мы расскажем о том, как работает операция "ромб" в случае отсутствия операнда, представляющего дескриптор файла. В этом случае эта операция может читать записи из стандартного файла ввода STDIN или получать информацию, передаваемую программе через командную строку.

Для отображения в стандартный файл вывода STDOUT используется уже знакомая нам функция print, которая, однако, может выводить информацию и в файл, определенный своим дескриптором.

Операция ввода команды

Заключенная в обратные кавычки "•"• строка символов является всего лишь удобной формой записи операции ввода команды операционной системы qx<>, с которой мы уже знакомы (см. главу 4).

Когда интерпретатор Perl встречает строковый литерал в обратных кавычках, он осуществляет подстановку в нее значений скалярных переменных и переменных массивов и передает получившуюся строку, как команду, на выполнение операционной системе. Последняя выполняет ее и возвращает в строковый литерал результаты вывода команды на стандартное устройство вывода, которым обычно является экран монитора. В связи с таким "поведением" строкового литерала в обратных кавычках его иногда называют псевдолитералом.

Операция ввода команды различает скалярный и списковый контексты, в которых она может выполняться. В скалярном контексте возвращается одна строка, содержащая весь вывод на экран монитора выполненной команды, включая символы новой строки в случае многострочного вывода. В списковом контексте возвращается список значений, каждое из которых содержит одну строку вывода. Пример 6.1 демонстрирует использование операции ввода команды в соответствующих контекстах.

При выполнении операции заключения в кавычки сначала осуществляется подстановка значения скалярной переменной $ command, а потом полученная строка передается на выполнение операционной системы. Переменная $scaiar (скалярный контекст) содержит весь вывод на экран монитора содержимого текущего каталога, поэтому при ее печати мы увидим все, что вывела команда dir. Когда результаты выполнения команды присваиваются массиву @iist (списковый контекст), то каждая строка вывода команды становится элементом массива, поэтому последний оператор печати примера 6.1 выводит первую и вторую строки.

В списковом контексте разбиение вывода команды операционной системы на элементы списка осуществляется в соответствии со значением встроенной переменной $/, которое используется в качестве разделителя. По умолчанию эта переменная содержит символ конца строки "\п" — поэтому и разбиение на элементы происходит по строкам. Присваивая этой переменной новое значение, мы тем самым определяем новое значение разделителя, которое будет использоваться при формировании элементов списка. Разделителем может быть любая последовательность символов. Например, в примере 6.2 в качестве разделителя задается строка "<КАТАЛОГ>".

dir s ; t Списковый контекст.
print $list[l], $list[2];

Теперь, в отличие от примера 6.1, элемент массива $iist[0j содержит не первую строку вывода команды dir, а вывод команды до первой встретившейся в нем последовательности символов "<КАТАЛОГ>". Аналогично, элемент $list[l] содержит вывод команды до следующей встретившейся последовательности СИМВОЛОВ "<КАТАЛОГ>" И Т. Д.

Команда, содержащаяся в псевдолитерале, выполняется всякий раз, как вычисляется этот псевдолитерал. Встроенная переменная $? содержит числовое значение состояния выполненной команды.

(Об интерпретации значений встроенной переменной $ ? см. главу 14.)

Замечание
Обобщенная форма операции заключения в обратные кавычки qx <> работает точно так же, как и операция заключения в обратные кавычки " * '".

Операция о

Для нашего читателя эта операция не является совсем уж новой. Несколько слов о ней было сказано в главе 4; в некоторых примерах мы ее использовали для ввода пользователем данных в программу Perl. Основное ее назначение — прочитать строку из файла, дескриптор которого является операндом этой операции. (Операнд операции о расположен внутри угловых скобок.) Мы не будем сейчас объяснять, что такое дескриптор файла, зачем он нужен и какую функцию выполняет в программах Perl. Эти вопросы будут нами подробно рассмотрены в следующей главе, посвященной работе с файлами. Здесь же мы остановимся на специальном случае использования этой операции — операции с пустым операндом о. В этом случае ввод осуществляется или из стандартного файла ввода, или из каждого файла, перечисленного в командной строке при запуске программы Perl. Но прежде чем перейти к описанию функционирования операции ввода с пустым операндом, остановимся на некоторых понятиях, необходимых для понимания дальнейшего.

При запуске программы Perl в системе UNIX или из командной строки Windows ей можно передать параметры. Эти параметры задаются после имени файла, содержащего программу Perl, и отделяются от него и друг от друга пробелами:

Perl program.pl parl par2 рагЗ

Параметрами могут быть ключи (обычно символ с лидирующим дефисом, например, -v), которые устанавливают определенные режимы работы программы, или имена файлов, содержимое которых должна обработать программа. Все передаваемые в программу параметры сохраняются в специальном встроенном массиве @ARGV. Если не передается ни одного параметра, то этот массив пуст.

Операция о без операнда, употребленная в циклах while и for, при первом своем вычислении проверяет, пуст ли массив @ARGV. Если он пуст, то в первый элемент этого массива $ARGV[O] заносится символ "-" и операция ожидает ввода пользователя из стандартного файла ввода STDIN. Если массив @ARGV не пуст, то он содержит параметры, переданные программе при ее запуске. Операция о трактует каждый из них как имя файла и в цикле передает в программу последовательно все строки всех файлов, указанных в командной строке. Рассмотрим простейшую программу (пример 6.4), состоящую из одного цикла while с операцией <>, и рассмотрим ее поведение при разных способах запуска.

i! Perl -w
while ($line = <>) print $line; >

При ее запуске без параметров она будет ожидать ввода пользователя с клавиатуры и в цикле распечатывать вводимые им строки, пока пользователь не завершит ввод комбинацией клавиш <Ctrl>+<Z>, интерпретируемой как конец файла.

Если при запуске передать ей имя файла, например, файла, содержащего саму же программу,

Perl examp6_4.pi examp6_4.pi

то программа примера 6.4 распечатает его содержимое:

f! Perl -w
while ($line = <>) print $line; >

Замечание
Предполагается, что программа примера 6.4 сохранена в файле с именем examp6_4.pl.

Если эту же программу запустить, задав в командной строке дважды имя файла программы,

Perl examp6_4.pl examp6_4.pl examp6_4.pl

то программа дважды распечатает свой собственный текст.

Замечание
В операционной системе Windows в именах файлов можно использовать пробелы. Для передачи в программу Perl файла с таким именем его следует заключать в двойные кавычки: "Name with blanks.dat".

При выполнении операции ввода из файла встроенная переменная $. на каждом шаге цикла хранит номер прочитанной строки файла. В случае задания нескольких имен файлов в командной строке при последовательном вводе их строк операцией о эта переменная продолжает увеличивать свое значение при переходе на чтение строк очередного файла, т. е. она рассматривает содержимое всех файлов как один-единственный файл.

Операцию о и массив @ARGV можно совместно использовать для ввода в программу содержимого нескольких файлов, не связывая их с заданием имен файлов в командной строке. В любом месте программы перед первым использованием в цикле операции ввода <> можно в массив SARGV занести имена файлов, содержимое которых необходимо обработать:

@ARGV = ("filel.dat", "file2.dat", "file3.dat"); for (;<>;) Операторы обработки строк файлов >

Этот фрагмент программы в цикле for последовательно обработает строки трех файлов filel.dat, file2.dat и file3.dat. Здесь же продемонстрирована еще одна интересная особенность операции ввода о. Обычно прочитанная этой операцией строка присваивается скалярной переменной, как это происходило в примере 6.4, но если эта операция одна представляет выражение условия цикла, то результат ее выполнения сохраняется в специальной встроенной переменной $_. Цикл while программы примера 6.4 можно записать и так:

Здесь также используется то обстоятельство, что функция print без параметров по умолчанию выводит содержимое переменной $_.

Если мы хотим передать в программу некоторые ключи, устанавливающие режим ее работы, то в начале программы следует поместить цикл, который проверяет содержимое массива @ARGV на наличие ключей в командной строке вызова программы. Один из способов подобной проверки приводится в примере 6.5, где предполагается, что программе могут быть переданы ключи

При вычислении выражения условия цикла while осуществляется присваивание переменной $_ значения первого элемента массива @ARGV и проверка присутствия дефиса "-" в качестве первого символа содержимого этой переменной (операция / Л -/). Операторы if проверяют содержимое переменной $_ на соответствие известным ключам и отображают их. (В реальных программах в этих операторах обычно определяют некоторые переменные, которые в дальнейшем используются для выполнения действий, присущих соответствующим ключам.) Функция shift удаляет из массива @ARGV первое значение, сдвигая оставшиеся в нем элементы на одну позицию влево: второй становится первым, третий вторым и т. д. Цикл повторяется до тех пор, пока переданные через командную строку параметры начинаются с дефиса. Еще одно применение операции <> связано с получением в программе имен файлов определенного каталога, удовлетворяющих заданному шаблону. Если в качестве операнда этой операции используется шаблон имен файлов, то в скалярном контексте она возвращает первое найденное имя файла в текущем каталоге, в списковом контексте — список имен файлов, удовлетворяющих заданному шаблону. (В шаблоне можно использовать метасимволы: * для произвольной цепочки символов, ? для произвольного одиночного символа.) Если в каталоге не найдены файлы с именами, удовлетворяющими шаблону, то операция возвращает неопределенное значение. Например, выполнение следующей операции

приведет к сохранению в переменной $ first имени первого файла из списка всех файлов текущего каталога с расширением pi, если таковые файлы в каталоге есть, иначе эта переменная будет иметь неопределенное значение. В списке файлы упорядочены в алфавитном порядке. Эта же операция в списковом контексте

возвращает список всех файлов с расширением pi. После выполнения этой операции элементы массива @files содержат имена всех файлов с расширением pi.

Замечание
Имена подкаталогов текущего каталога считаются файлами без расширения. Например, в возвращаемом операцией <*. *> списке файлов будут содержаться и имена подкаталогов текущего каталога.

Если при задании шаблона файла явно указать каталог, то эта операция возвратит список файлов из указанного каталога, имена которых удовлетворяют заданному шаблону. Например, операция

сохранит в массиве @flies имена всех файлов каталога /Perl с расширением pi.

Замечание
В системе Windows эта операция найдет все файлы с расширением р! в каталоге /Perl текущего диска. Для задания конкретного диска следует использовать принятый в Windows синтаксис для полного имени файла: <d: /Perl/*. *>. Эта операция возвратит список всех файлов каталога /Perl, расположенного на диске d:.

При использовании этой операции в выражении условия цикла while или for она последовательно на каждом шаге цикла возвращает очередное имя файла, удовлетворяющее заданному шаблону:

while ($file = <*.pl>) (
print "$file\n"; >

Употребленная в выражении условия самостоятельно, эта операция возвращает очередное имя файла в переменной $_. Например, предыдущий фрагмент можно переписать следующим образом:

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

• @scripts = glob "*.pl";

В скалярном контексте она возвращает имя первого файла, удовлетворяющего заданному шаблону, в списковом — список имен всех файлов. Употребленная без параметра, она использует в качестве параметра специальную переменную $_.

Функция print

Функция print наиболее часто используемая функция для вывода информации из сценария Perl. Ее синтаксис имеет следующий вид:

print ДЕСКРИПТОР СПИСОК;

Здесь ДЕСКРИПТОР представляет дескриптор файла, в который функция выводит строковые данные, представленные списком вывода список. Он может состоять из переменных, элементов массивов и выражений, вычисляемых как строковые данные. Дескриптор файла создается функцией open 0,0 которой мы поговорим в следующей главе. Он может быть опущен, и в этом случае вывод осуществляется в стандартный файл вывода STDOUT, если только функцией select о не выбран другой файл вывода по умолчанию. Как уже отмечалось ранее, обычно стандартное устройство вывода — экран монитора компьютера.

Функция print при выводе своего списка не завершает его символом новой строки "\п". Это означает, что следующая функция print начнет вывод на экран непосредственно после последнего выведенного предыдущей функцией print символа. Если такое поведение не желательно, то следует список вывода каждой функции print явно завершать строкой, содержащей символ новой строки, или включать его последним символом последнего элемента списка вывода. Пример 6.6 демонстрирует вывод с помощью функции print.

Вывод первых четырех функций print примера 6.6 представлен ниже:

String I:String 2: String 3: String 4:

Вторая функция print начинает свой вывод на той же строке, на которой завершила вывод первая функция, в которой в списке вывода нет символа перехода на новую строку. В четвертой функции явно указан дескриптор стандартного файла вывода STDOUT. Относительно пятой функции скажем, что она ничего ни в какой файл, определенный дескриптором FILEOUT, не выведет, так как с этим дескриптором не связан никакой файл. Для этого следовало бы до выполнения последней функции print открыть файл функцией open о и связать с ним дескриптор FILEOUT. Мы отложим эти вопросы до следующей главы.

Функция print, как и большинство других функций, определенных в языке Perl, является списковой операцией, и все элементы списка вывода вычисляются в списковом контексте. Это обстоятельство следует учитывать при использовании в качестве элементов списка вывода выражений с вызовами подпрограмм.

Все, что было сказано относительно списковых операций и их использования в качестве термов выражений в главе 4, относится, естественно, и к функции print. Если ее параметры, включая дескриптор файла, заключены в круглые скобки, то такая синтаксическая конструкция считается термом и в выражении имеет наивысший приоритет вычисления. Например, следующий оператор

напечатает сумму значений переменных $т и $п, а не их сумму, возведенную в квадрат. Компилятор Perl, обнаружив после лексемы print левую круглую скобку, найдет правую круглую скобку и будет рассматривать их содержимое как список параметров функции print. А так как такая конструкция есть терм, то сначала будет выполнена операция печати суммы значений переменных, а потом результат этой операции (Истина =1) будет возведен в квадрат. Добавление необязательного дескриптора стандартного файла вывода STDOUT исправит подобную ошибку:

Если в функции печати print не задан список вывода, то она по умолчанию выводит содержимое специальной переменной $_ в файл, определенный параметром ДЕСКРИПТОР:

В этой главе мы познакомились с основными возможностями ввода/вывода, предоставляемыми языком Perl. Узнали, как легко и просто можно выполнить команду операционной системы и получить результаты ее вывода на экран монитора непосредственно в программу Perl. Операция <> позволяет не только считывать записи внешних файлов, но и автоматически обрабатывать содержимое нескольких файлов, заданных в командной строке при запуске сценария Perl. Эта же операция позволяет осуществлять поиск файлов, чьи имена удовлетворяют заданному шаблону. Для вывода информации из программы используется функция print о, которая может выводить ее не только на экран монитора (стандартное устройство вывода), но также и во внешний файл.

Читайте также: