Введение в Perl

         

My список



my список

Объявляет локальными переменные в списке. Если два или более имени, их необходимо заключить в круглые скобки.



Next метка next



next метка
next

Аналогичен continue в С. Переход к следующей итерации в цикле. Если в цикле присутствует блок continue, он так же выполняется. Если метка отсутствует - переход на ближайший внутренний цикл.



Next подобен continue в С Переходит



next - подобен continue в С. Переходит к началу текущего цикла т.е. повторяет итерацию.



No Module список



no Module список.

Исключить использование указанных модулей.





Oct выражение



oct выражение

Возвращает десятичное число, представленное восьмеричными цифрами.



Open файл выражение open файл



open файл, выражение
open файл

Открыть файл с указанным именем. Аргумент "файл" - это фактически указатель на блок описания файла. Если имя (выражение) файла отсутствует, то имя считается таким же как и указатель файла. Если перед именем стоит символ '<' то файл открывается только на чтение (значение по умолчанию). Если '>' - на запись. Если '>>' - на добавление записей. '+>' или '+<' - файл открыт на чтение и запись одновременно. Если имя файла начинается с символа '|', то имя считается системной командой, на вход которой выводятся данные (поток). Имя '-' - стандартный вход (STDIN), '>-' - стандартный вывод (STDOUT). Функция возвращает true при успехе и false - неудаче.

Если имя (выражение) начинается с символов ">&", то остаток имени считается именем указателя файла, который открывается повторно. Символ '&' может стоять после '<', '>>', '+>', '+>>' и '+<'. Режим повторного открытия должен соответствовать первому. Выражение вида "<&=N" где N -число, эквивалентно системному вызову fdopen(). Если имя "|-" или "-|", то происходит "расщепление" (fork) процесса на потомка и родителя. При этом возвращается номер процесса потомка (PID) внутри родительского процесса и 0 - внутри потомка. При этом запись/чтение в файл родительским процессом воспринимается как чтение/запись потомком. Для потомка это стандартный ввод/вывод. Родительский процесс ждет завершения потомка после закрытия потока и получает код завершения в переменной $?. Имя файла не должно содержать пробелов как в начале, так и в конце.



Opendir указатель выражение



opendir указатель, выражение

Открыть директорию с именем выражения для обработки функциями readdir(), telldir(), seekdir(), rewinddir() и closedir(). Возвращает true при успехе.



Оператор диапазона ' '



Оператор диапазона '..'

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



Оператор goto



Оператор goto.

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

В Perl реализовано три формы goto. goto - метка, goto - выражение и goto - подпрограмма.

goto goto - выражение goto подпрограмма
метка выполняет непосредственный переход на указанную метку.
Вычисляет имя метки и делает соответствующий переход. Например если мы хотим сделать переход на одну из трех меток "M1:", "M2:" или "M3:" в зависимости от значений переменной $i равной 0, 1 или 2 то это лучше сделать следующим образом: goto ("M1", "M2", "M3")[$i];

здесь $i используется как индекс массива указанного непосредственно в выражении.

довольно редкий случай т.к. всегда проще и надежней вызвать подпрограмму "естественным" образом.


Оператор 'X'



Оператор '-X'.

-X указатель файла -X выражение -X

Проверка файла, где 'X' - одно из ниже описанных значений. Это унарный оператор с одним аргументом - либо именем файла, либо указателем файла. Проверяет одно из условий. Если аргумент не указан, то берется значение переменной $_. Для ключа -t - STDIN. Результат 1, если true, '', если false или неопределенное значение, если файл не найден. Несмотря на странный вид это унарный оператор с соответствующим приоритетом. Аргумент можно заключать в круглые скобки. 'X' имеет следующие значения:

-r Файл разрешен на чтение эффективным uid/gid
-w на запись -//-
-x исполнение -//-
-o принадлежит эффективному uid (идентификатор пользователя)
-R Файл разрешен на чтение реальным uid/gid
-W на запись -//-
-X исполнение -//-
-O принадлежит реальному uid
-e файл существует
-z пустой
-s не пустой
-f обычный текст
-d директория
-l символическая ссылка
-p pipes (конвейер)
-S socket (гнездо)
-b специальное блочное устройство
-c -//- символьное -//-
-t указатель на уст-во tty
-u установлен бит setuid
-g -//- setgid
-k -//- sticky
-T текстовой файл
-B двоичный
-M "возраст" файла в днях на момент старта скрипта
-A дней с последнего чтения
-C дней с последней модификации inode


Оператор ' ' (запятая)



Оператор ',' (запятая)

В скалярном контексте выполняется левый аргумент, результат игнорируется, затем правый и его результат есть результат действия оператора. В списковом контексте это разделитель элементов списка, который включает указанные элементы в список.



Операторы и приоритеты



Операторы и приоритеты.

Термы и левосторонние списковые операторы Унарные операторы Операторы "привязки" =~ и != Мультипликативные операторы Аддитивные операторы Операторы сдвига Именованные унарные операторы Операторы отношений Операторы равенства Операторы работы с битами Логические операторы && (AND) и || (OR) Оператор диапазона '..' Условный оператор '?:' Операторы присваивания Оператор ',' (запятая) Логические not, and, or, xor Операторы ограничители строк Операторы ввода-вывода Слияние констант Целочисленная арифметика

В Perl ассоциативность и приоритетность операторов аналогична языку С. Ниже перечислены все операторы в порядке уменьшения приоритета, в начале строки указана ассоциативность.

ассоц. операторы
левая термы и левосторонние списковые операторы
левая ->
- ++ --
правая **
правая ! ~ \ унарные + и -
левая =~ !~
левая * / % x
левая + - .
левая << >>
- именованные унарные операторы
- < > <= >= lt gt le ge
- == != <=> eq ne cmp
левая &
левая | ^
левая &&
левая ||
- ..
правая ?:
правая = += -= *= и т.д.
левая , =>
- правосторонние списковые операторы
левая not
левая and
левая or xor


Операторы not and or xor



Операторы not, and, or, xor

Оператор логическое not (отрицание).
Унарный not возвращает противоположное значение, полученное выражением справа. Он эквивалентен '!', но имеет очень низкий приоритет.

Оператор логическое and (И).
Выполняет логическую конъюнкцию двух выражений. Эквивалентен '&&', но имеет очень низкий приоритет и "краткость" действия, т. е. если левое выражение равно false - левое не выполняется.

Логическое or (ИЛИ).
Выполняет логическую дизъюнкцию двух выражений. Эквивалентен '||', но имеет очень низкий приоритет и "краткость" действия, т. е. если левое выражение равно true - левое не выполняется.

Логическое xor (исключающее ИЛИ).
Выполняет логическое исключающие или. Всегда выполняются оба правое и левое выражение.

В Perl отсутствуют операторы языка С такие как:

унарное & - получить адрес. Для этого применяется '\'.
унарный * - переадресация.
(TYPE) - совмещение типов.


Операторы ограничители строк



Операторы ограничители строк.

Обычно ограничителями строк мы считаем литералы, но в Perl это операторы выполняющие разного рода интерполяцию и поиск по шаблону. Вы можете сами задавать удобные для вас ограничители. В следующей таблице приведен полный перечень вариантов. Фигурные скобки '{}' обозначают любой символ, используемый для ограничителя. В случае использования скобок (круглых '()', квадратных '[]', фигурных '{}', угловых '<>') в начале ставится открывающаяся скобка, а в конце закрывающая.

По умолчанию Полное Функция Интерполяция
'' q{} Literal нет
"" qq{} Литерал да
`` qx{} Команда да
qw{} Список слов нет
// m{} Шаблон да
  s{}{} Подстановка да
  tr{}{} Трансляция нет

В строках допускающих интерполяцию имена переменных, начинающиеся с символов '$' или '@' - интерполируются, т.е. в строку вставляется значение строки или массива. Данные последовательности символов имеют специальное значение:

\t символ табуляции
\n символ новой строки
\r возврат
\f перевод формата
\v вертикальная табуляция
\b backspace (забой)
\a звонок
\e escape
\034 восьмеричный символ
\x1a шестнадцатеричный символ
\c[ символ управления
\l нижний регистр следующего символа
\u верхний регистр следующего символа
\L нижний регистр для всех символов до \E
\U верхний регистр для всех символов до \E
\E ограничитель смены регистра
\Q отмена действия метасимволов до \E

Шаблоны интерполируются как регулярные выражения. Это выполняется вторым проходом после интерполяции переменных, поэтому в шаблоны можно вставлять переменные. Для отмены интерполяции используйте '\Q'. Если вы применяете вложенные ограничители, то внутренние ограничители работать не будут.



Операторы отношений



Операторы отношений.

'<' - арифметическое меньше
'>' - арифметическое больше
'<=' - арифметическое меньше или равно
'>=' - арифметическое больше или равно
'lt' - строковое меньше
'gt' - строковое больше
'le' - строковое меньше или равно
'ge' - строковое больше или равно


Операторы присваивания



Операторы присваивания.

'=' - обычный оператор "присвоить" правое значение переменной слева

Вся эта группа операторов подобна операторам С, т.е.

$i += 2;

эквивалентно

$i = $i + 2;

Остальные операторы этой группы работают аналогично. Допустимы следующие операторы:

**=
+=, -=, .=
*=, /=, %=, x=
&=, |=, ^=
<<=, >>=
&&=, ||=

Приоритет всей этой группы операторов равен приоритету '='.



Операторы "привязки" =~ и !=



Операторы "привязки" =~ и != .

Эти "необычные", я бы даже сказал, оригинальные операторы имеют очень широкое применение в Perl. Можно даже назвать их "оригинальным" решением. Оператор =~ логически связывает левую часть выражения с патерном (pattern - образец, шаблон, модель) в правой. По умолчанию поиск или изменение по патерну выполняется в переменной $_ Операторы привязки позволяют делать это с любой переменной, указанной в левой части. Логическим результатом будет успех операции. Если в правой части вместо патерна присутствует выражение, то результат этого выражения воспринимается как патерн. Однако это не очень эффективно, т.к. патерн будет компилироваться во время исполнения программы, что заметно снизит быстродействие. Оператор != аналогичен =~, только результат совпадения инвертируется (логическое "нет"). Подробное применение этих операторов приводится в главе Патерны.



Операторы работы с битами



Операторы работы с битами.

'&' - побитное AND
'|' - побитное OR
'^' - побитное XOR


Операторы равенства



Операторы равенства.

'==' результат true если левая часть равна правой (равно)
'!=' - не равно
'<=>' - -1 если левая часть меньше правой, 0 если равна,
1 если больше.
'eq' - строковое равно
'ne' - строковое не равно
'cmp' - как и '<=>' применительно к строкам


Операторы сдвига



Операторы сдвига.

'<<' - Сдвигает побитно влево значение выражения в левой части
на количество бит указанное в правой.
'>>' - Сдвигает побитно вправо значение выражения в левой части
  на количество бит указанное в правой.


Операторы управления циклом



Операторы управления циклом.



Операторы вводавывода



Операторы ввода-вывода.

В Perl существует несколько операторов ввода-вывода. Первый это скобки из символа '`' - акцента. Строка в этих скобках воспринимается как системная команда и результат ее действия возвращается как "псевдо" литерал. В скалярном контексте это строка содержащая весь результат, а в списковом - список, элементы которого - строки результата. Статус выполненной команды хранится в переменной $? .

Следующая команда ввода вывода выглядит как '<файл>'. Вычисление <файл> приводит к чтению строки из файла. Обратите внимание, что 'файл' здесь не имя файла, а указатель файла, который создается функцией open(). В скалярном контексте читается одна строка вместе с символом '\n' - перевода строки, а в списковом весь файл читается в список, элементы которого суть строки файла. В случае обнаружения конца файла результат оператора не определен и воспринимается как false. Если не указана переменная результата, то по умолчанию это $_. Указатель файла по умолчанию STDIN - стандартный ввод.



Ord выражение



ord выражение

Возвращает ascii код первого символа выражения.



От простого к сложному



От простого к сложному

Прежде чем приступить к последовательному ознакомлению с не знакомым для вас языком, должен оговориться и сказать, что все примеры да и сам язык описанию которого посвящена эта книга это Perl версии 5.003 для операционной системы FreeBSD версии 2.01. Существуют реализации этого языка для операционных систем OS/2 , MS-DOS и Windows NT но они немного отстают по возможностям от оригинала, рожденного в недрах Unix.



Отладка Perl программ



Отладка Perl программ.

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

Команды отладчика.

h - Получить справку по командам. T - Просмотреть стек программы s - Выполнить одну команду и остановиться. n - Выполнить подпрограмму и остановиться. r - Выполнить текущую подпрограмму и остановиться. c - Продолжить выполнение до следующей точки остановки. c номер - Продолжить выполнение до строки с данным номером. - Повторить последнюю команду n или s. l min+incr - Вывести incr+1 строк программы начиная со строки min. l min-max - Вывести строки начиная с min до max. l номер - Вывести строку с указанным номером. l - Вывести следующий экран строк. - - Вывести предыдущий экран строк. w строк - Вывести экран строк. Текущая в середине. l подпрограмма - Вывести строки указанной подпрограммы. /шаблон/ - Найти строку в тексте программы. ?шаблон? - Обратный поиск строки в тексте программы. L - Вывести строки с точками останова и активами. S - Вывести имена всех подпрограмм. t - Включить или выключить трассировку. b строка [ условие] - Установить точку остановки. b подпрограмма [ условие ] - Установить точку остановки в начале указанной подпрограммы и если указано при данном условии. d - Убрать точку остановки. D - Убрать все точки остановки. a строка команда - Установить актив (команду которая выполнится вместе с указанной строкой. "команда" - обычная команда Perl. A - Стереть все активы. - Выполнять команду перед каждой остановкой. > команда - Выполнить команду после остановки отладчика. V модуль [имена] - Вывести значение всех или указанных имен в модуле. Внимание! Символ '$' не вводится. X [имена] - То же что и V , но только для текущего модуля. ! номер - Выполнить одну строку программы. ! -номер - Выполнить одну команду с номером предшествующим текущей строке. H - n - Вывести n последних выполненных команд. q или ^D - Выход из программы. команда - Выполнить команду Perl. p выражение - Вывести значение выражения.

Конструктор BEGIN не отслеживается отладчиком, но можно в теле конструктора указать:

$DB::single =1;

и отладчик остановится. Данная команда не вызовет ошибку при работе без отладчика.



Pack шаблон список



pack шаблон, список

Упаковывает список в двоичную структуру по шаблону. Шаблон - это строка символов, описывающая порядок и тип упакованных значений.

A - текстовая строка, добавляется пробелами. a - текстовая строка, добавляется 0 символом. b - битовая строка (возрастающая нумерация бит) B - битовая строка (убывающая нумерация бит) h - шестнадцатеричная строка ( младший байт - первый) H - шестнадцатеричная строка (старший байт первый) c - символ со знаком C - символ без знака. s - короткое целое (один байт) со знаком. S - короткое целое без знака. i - целое (два байта) со знаком. I - целое без знака. l - длинное целое (4 байта) со знаком. L - длинное целое без знака. n - короткое в "сетевом" формате. N - длинное в "сетевом" формате. v - короткое в "VAX" формате. V - длинное в "VAX" формате. f - single float. F - double float. p - указатель на строку ограниченную 0. P - указатель на структуру с фиксированной длиной. u - упаковка uuencode. x - нуль-байт X - резервный байт. @ - заполнить нулями позицию.

За каждой буквой может стоять число означающее количество повторов. Для всех типов за исключением 'a', 'A', 'b', 'B', 'h' и 'H', упаковывается максимально возможное количество значений из списка. Символ '*' после типа означает использовать оставшиеся параметры. Тип 'a' и 'A' использует только одно значение из списка и добавляет остаток поля либо нуль-символами, либо пробелами (при распаковке по типу 'A' пробелы и нули отбрасываются, а по 'a' - нет). Типы 'b' и 'B' упаковывают строку в указанное число бит. Так же как и 'h' и 'H' в число ниблов (байт). 'P' - упаковывает указатель на структуру с указанной длиной. Числа с плавающей запятой (floats и double) записываются в стандартном для каждой машины формате и могут быть разными для разных типов машин. Заметьте, что Perl всегда использует двойную точность (double), поэтому упаковка и распаковка по типу 'f' приведет к потере точности. Шаблоны для распаковки и упаковки совершенно одинаковы.



?PATERN?



?PATERN?

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

m/PATERN/gimosx
/PATERN/gimosx

Поиск в строке по патерну (шаблону). В скалярном контексте возвращает логическое значение true (1) или false (''). Если строка не указана с помощью операторов '=~' или '!~', поиск ведется в строке $_ Опции:

g - Глобальный поиск. Поиск всех вхождений.
i - Сравнение не зависит от регистра (верхний или нижний)
m - Строка многострочная.
o - однопроходная компиляция
s - однострочная строка
x - используются расширенные регулярные выражения.

Если '/' - ограничитель, то начальное 'm' можно опустить. С помощью него в качестве ограничителя может быть любой символ кроме пробела.

PATTERN может содержать переменные, которые будут интерполироваться (перекомпилироваться) каждый раз в момент вычисления. Переменные $) и $| не интерполируются. Если вы хотите, что бы такой шаблон интерполировался один раз - добавьте /o. Это необходимо делать в циклах поиска для увеличения быстродействия, однако, если вы измените значение переменной, Perl этого даже не заметит.

Если PATERN - нулевая строка, то используется последнее регулярное выражение.

В скалярном контексте возвращается список элементы которого - результаты выполнения выражений в скобках патерна ($1, $2, $3...). Обратите внимание что первый элемент $1.



Переменные



Переменные.

Контекст Скалярные значения Конструкторы скаляров Конструкторы списков Тип typeglobs

В Perl существует три типа структур данных: скаляры, массивы скаляров и хеши (hashes) - ассоциативные массивы скаляров. Обычно элементы массивов индексируются целыми числами, первый элемент - нулевой. Отрицательное значение индекса обозначает номер позиции элемента с конца. Хеши индексируются строками символов.

Имена скалярных переменных всегда начинаются с символа '$' даже когда обозначают элемент массива.



Переменные типа local



Переменные типа local.

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



Переопределение встроенных функций



Переопределение встроенных функций.

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

use subs 'функция1', 'функция2' ....; и далее в модуле определить сами функции.

Pipe READHANDLE WRITEHANDLE



pipe READHANDLE, WRITEHANDLE

Аналогичен системному pipe().



POD операторы Документирование программ



POD операторы. Документирование программ.

В Perl реализован очень удобный механизм для написания документации в момент создания программы. Для этого применяются специальные POD операторы. Если в теле программы интерпретатор встречает оператор начинающийся с символа '=' например:

= head Набор стандартных процедур

то пропускается все до слова '=cut'. Это удобно для включения длинных на несколько строк или страниц комментариев. Затем с помощью специальной программы pod можно отделить текст документации от текста программы.



Подпрограммы



Подпрограммы.

Private переменные Переменные типа local Прототипы (prototypes) Ссылка как параметр Переопределение встроенных функций Автозагрузка

Для применения подпрограммы ее необходимо определить либо в текущем модуле (файле), либо во внешнем модуле (файле). Подпрограммы определяются и декларируются следующим образом:

sub имя; - Только декларация. Определение ниже. sub имя (прототипы); - То же но с декларацией параметров. sub имя блок; - Декларация и определение. sub имя (прототипы) блок; - То же, но с параметрами.

Для определения динамической анонимной подпрограммы можно указать:

$переменная = sub блок;

Для импортирования подпрограмм из других модулей используйте:

use модуль qw(подпрограмма1 подпрограмма2 );

Вызов подпрограммы:

имя(список параметров); # символ '&' можно не указывать. имя список; # Если подпрограмма уже декларирована. &имя; # Параметры в @_

Все параметры передаются подпрограмме как массив @_. Соответственно $_[0] - первый параметр, $_[1] - второй и т.д. Массив @_ - локальный, но он содержит адреса параметров, поэтому можно изменять значение параметров. Возвращаемое значение подпрограммы - результат последнего оператора. Это может быть как скаляр так и массив. Можно принудительно возвращать результат используя функцию return().

Подпрограмму можно вызвать, используя префикс '&' перед именем подпрограммы. Если подпрограмма предварительно продекларирована, то префикс и скобки можно опустить.



Pop массив



pop массив

Удаляет и возвращает последний элемент массива. Длина массива уменьшается на 1. Результат не определен, если массив пустой. Если имя массива отсутствует, то извлекает из @ARGV для головной программы и @_ для подпрограммы.



Pos скаляр



pos скаляр

Возвращает смещение от последнего m//g поиска.



Pragma библиотеки



Pragma библиотеки.

Данные библиотеки используют как:

use имя;

когда хотят включить действие и

no имя;

когда выключить.

В стандартный набор входят следующие pragma:

diagnostics
Включить режим расширенной диагностики.

integer
Использовать целочисленную арифметику.

less
Режим минимальной загрузки компилятора.

overload
Режим переопределения операторов.

sigtrap
Режим слежения за прерываниями.

strict
Режим ограниченного использования "опасных" операторов.

subs
Режим обязательного декларирования подпрограмм.



А теперь подробно разберем каждую



Пример 1

#!/usr/local/bin/perl # Содержимое файла test1.pl print "Наше Вам с кисточкой!\n"; А теперь подробно разберем каждую строку.

#!/usr/local/bin/perl

Данная строка должна быть первой в любой Perl-программе. Она указывает системному интерпретатору что данный файл - это Perl-программа.
# Содержимое файла test1.pl Эта строка называется комментарием. Она всегда начинается символом '#' и заканчивается таким объяснением что как говорил великий Ходжа Насреддин "это тонкий философский вопрос", а говоря простым языком здесь можно писать все что угодно. Даже пожелание руководству. Уж здесь оно точно до него не дойдет.
print "Наше Вам с кисточкой!\n";

Самая последняя ну и конечно главная. Она просто выводит на экран надпись "Наше Вам с кисточкой!".

Здесь слово print - это команда "вывести". Все что в кавычках - это символы, \n - перевод строки и ';' - признак конца команды. Он обязателен. В одной строке может быть несколько команд и все они должны завершаться символом ';'. После него может быть символ '#' - это значит остаток строки считается комментарием.

Над этой строкой автору пришлось больше всего поломать голову так как в нее постоянно лезли какие то странные "hello", "hello all", "Построимся и спасемся", "Строй наше спасение" и т. д. и т.п.

Если вы никогда не работали с Perl, то бьюсь на спор в 10$, что данная программа сразу у вас не заработает! Не потому что она не верна, а потому что "Нельзя объять необъятное". Сразу, потом можно, да и то частями. Сначала сделайте ваш файл test1.pl исполняемым. Для этого введите команду:
chmod +x test1.pl Затем проверьте где у вас Perl. Для этого введите:
which perl Система вам выдаст что то вроде: /usr/bin/perl
Если:
perl: Command not found. То тогда закройте книжку и ложитесь спать. У вас просто нет Perl или он не установлен. А мне остается послать вас к системному администратору или к man (для переводчиков- man сокращение от manual а не то что вы подумали).

Теперь проверьте что бы строка 01 содержала то что выдала команда which. Если совпало то введите:
test1.pl и бьюсь на 50$, что и теперь программа не заработает, так как правильней ввести:
./test1.pl

Если я проиграл, то не радуйтесь. Да же если вам удалось запустить программу как test1.pl это значит, что у вас будут неприятности в будущем.


Пример 1

$var1 # Простой скаляр 'var1' $var1[0] # Первый элемент массива 'var1' $var1{'first'} # Элемент с индексом 'first' В случае использования имени массива "целиком" или его "среза" перед именем массива ставится символ '@'.



Пример 1

#!/usr/local/bin/perl # # Программа печати пригласительного билета # $кому = "Чапаеву Василию Ивановичу"; $от_кого = "Компания МММ"; $адрес = "Москва, ул. Петровка, д 38"; $текст = " Уважаемый Василий Иванович! Компания МММ имеет честь пригласить Вас и Ваших близких на презентацию наших новых хромовых сапог, сделанных на уровне мировых стандартов качества и дизайна."; format STDOUT = П Р И Г Л А С И Т Е Л Ь Н Ы Й Б И Л Е Т ---------------------------------------------------------------------- Кому: @ Результат:
П Р И Г Л А С И Т Е Л Ь Н Ы Й Б И Л Е Т ---------------------------------------------------------------------- Кому: Чапаеву Василию Ивановичу | Уважаемый Василий Иванович! | Компания МММ имеет честь От кого: Компания МММ | пригласить Вас и Ваших близких | на презентацию наших новых Адрес:Москва, ул. Петровка, д 38 | хромовых сапог, сделанных на | уровне мировых стандартов | качества и дизайна. | ---------------------------------------------------------------------- Отпечатано в типографии ИТУ 38 Специальные переменные:
$~ - построчный формат содержимого. $^ - формат заголовка листа. $% - номер листа. $= - строк в листе. Если вы хотите использовать одни и те же форматы для разных файлов, то самый простой путь:
use FileHandle; # Указать в начале программы format_name файл имя_формата; # Формат содержимого листа. format_top_name файл имя_формата; # Формат заголовка листа. write(файл); # вывод данных. Здесь 'файл' имеется ввиду указатель файла полученный командой open();
Если вам нужно в теле листа выводить разного рода форматы (например заголовки групп или отбивку листа), то применяйте format_name.



Пример 1

print 1 + 2 + 3; # результат 6 print(1+2)+3; # результат 3 print (1+2)+3; # опять 3 print (1+2+3); # 6 Если функция возвращает результат как в скалярном так и в списковом контексте, то код выхода по ошибке - скаляр c неопределенным значением или пустой список.
Запомните правило:
Не существует общего правила преобразования списка в скаляр!
Каждый оператор и функция имеют свой вид значения в скалярном контексте. Для одних это количество элементов из скалярного контекста. Для других - первый элемент списка или последний или количество успешных операций. Каждый - свое, если вы специально не указываете.
Оператор '-X', abs, accept, alarm, atan2 Y, X, bind, binmode, bless, caller, chdir, chmod, chomp, chop, chown, chr, chroot, close, closedir, connect, cos, crypt, dbmclose, dbmopen, define, delete, die, do BLOCK, do подпрограмма, do выражение, dump, each, eof, eval, exec, exists, exit, exp, fcntl, fileno, flock, fock, format, formline, getc, getlogin, getpeername, getpgrp PID, getppid, getpriority, Группа системных вызовов, getsockname, getsockopt, glob, gmtime, goto, grep, hex, import, index, int, ioctl, join, keys, kill, last, lc, lcfirst, length, link, listen, local, localtime, log, lstat, m//, map, mkdir, msgctl, msgget, msgsnd, msgrcv, my, next, no Module, oct, open, opendir, ord, pack, pipe, pop, pos, print, printf, push, q/строка/, qq/строка/, qx/строка/, qw/строка/, quotemeta, rand, read, readdir, readlink, recv, redo, ref, rename, require, reset, return, reverse, rewindir, rindex, rmdir, s///, scalar, seek, seekdir, select, select RBITS, WBITS, EBITS, TIMEOUT, semctl, semget, semop, send, setpgrp, setpriority, setsockopt, shift, shmget, shmget, shmread, shutdown, sin, sleep, soket, soketpair, sort, splice, split, sprintf, sqrt, srand, stat, study, substr, symlink, syscall, sysread, system, syswrite, tell, telldir, tie, time, times, tr///, truncate, uc, ucfirst, umask, undef, unlink, unpack, untie, unshift, use, utime, values, vec, wait, waitpid, wantarray, warn, write, y///



Пример 1

print ++($i = "09"); # Результат "10" print ++($i = "a9"); # "b0" print ++($i = "az"); # "ba" print ++($i = "aZ"); # "bA" Оператор ** (возведение в степень)



Пример 1

$s = "Один 1 два 2 и три 3"; if ($s =~ /(\d+)\D+(\d+)/) { print "$1\n";# Результат '1' print "$2\n";# '2' print "$+\n";# '2' print "$&\n";# '1 два 2' print "$`\n";# 'Один ' print "$'\n";# ' и три 3' } Perl версии 5 содержит дополнительные конструкции шаблонов:

(?#комментарий) - комментарий в теле шаблона.
(?:шаблон) - группировка как и '( )', но без обратной ссылки
(?=шаблон) - "заглядывание" вперед. Например /\w+(?=\t)/ соответствует слову, за которым идет табуляция, но символ '\t' не включается в результат.




Пример 1

# Программа вычисления факториала. print fact(3); # вычислить факториал 3*2*1 sub fact # Определяем подпрограмму. { my $m; # private переменная но не local ! $m = $_[0]; return 1 if $m Можно указывать начальные значения private переменных как:
my(список) = выражение; Так для вышеприведенного примера лучше было написать: my($m) = $_[0];



Пример 1

sub test; # Декларация подпрограммы test $var1 = test $0; # Использование как оператора списка. Декларации подпрограмм могут быть загружены из отдельного файла предложением require или загружены и импортированы в текущую область имен предложением use. Подробно см. главу Модули.

Читать по одной строке файла



Пример 2

#!/usr/local/bin/perl open(PASS, "</etc/passwd") || die "Файл не найден!"; while(<PASS>) { print; } close(PASS); Пояснения:

open(PASS, "</etc/passwd") || die "Файл не найден!"; "Открыть" файл, т.е. создать указатель файла PASS, и в случае ошибки выдать "Файл не найден!" и закончить программу.
while(<PASS>) Читать по одной строке файла в переменную по умолчанию $_.
{ Открыть блок операторов.
print; Вывести на экран переменную по умолчанию $_
} Конец блока.
close(PASS); Закрыть файл. Этого можно и не делать, т. к. файл автоматически закроется после окончания программы.

Результат работы этой программы тот же что и команды cat /etc/passwd. По экрану пробежали непонятные строки но зато теперь перед вами открыты горизонты Perl программирования! Все последующие примеры будут развитием этой программы и она превратится из гадкого утенка в прекрасного лебедя (не генерала).


Пример 2

@var1 # Все элементы массива var1 ( $var1[0], $var1[1], ... $var1[n]) @var1[1,3,10] # Элементы $var1[1], $var1[3], $var1[10] @var1{'first','last'} # то же что и ( $var1{'first'}, $var1{'last'} ) Хеш "целиком" начинается с символа '%'.



Пример 2

chmod 0666 'f1', 'f2', 'f3';



Пример 2

print 4**2 # Результат 16 print -4**2 # Результат -16 т.е. -(4**2)



Пример 2

$s = "1+2-3*4"; if ($s =~ /(\d)(?=-)/) # Найти цифру за которой стоит '-' { print "$1\n"; # Результат '2' } else { print "ошибка поиска\n";} (?!шаблон) - "заглядывание" вперед по отрицанию.



Пример 2



Пример 2

$var = 1; $var2 = 3 if $var > 0; # Результат: $var2 = 3 while EXPR - Модификатор "пока". Предложение выполняется пока EXPR = true

Присвоить указанным переменным поля входной



Пример 3

#!/usr/local/bin/perl open(PASS, "</etc/passwd") || die "Файл не найден!"; while(&ltPASS>) { ($login, $pass, $uid, $gid, $name, $home_dir, $shell) = split(':'); print "$login \t $name\n"; } close(PASS); Пояснение:
($login, $pass, $uid, $gid, $name, $home_dir, $shell) = split(':'); Присвоить указанным переменным поля входной строки, считая разделителем символ ':'.
print "$login \t $name\n"; Вывести login - имя пользователя и его описание. Поля разделены символом '\t' - табуляции.


Пример 3

%var, %key, %years Имена подпрограмм начинаются символом '&', если из контекста не видно, что это подпрограмма.



Пример 3

print(pack("ccc",65,66,67)); # Результат ABC print(pack("A4A3","ab","cdefg")); # "ab cde" print(pack("a4a3","ab","cdefg")); # "ab\0\0cde"



Пример 3

print '*' x 5; # Результат '*****' print (1,2) x 3; # Результат 121212



Пример 3

$s = "1+2-3*4"; if ($s =~ /(\d)(?!\+)/) # Найти цифру за которой не стоит '+' { print "$1\n"; # Результат '2' } else { print "ошибка поиска\n";} (?ismx)- "внутренние" модификаторы. Удобно применять в шаблонах, где например нужно внутри шаблона указать модификатор.
Правила регулярного выражения. (regex)
Любой символ обозначает себя самого, если это не метасимвол. Если вам нужно отменить действие метасимвола, то поставьте перед ним '\'. Строка символов обозначает строку этих символов. Множество возможных символов (класс) заключается в квадратные скобки '[]', это значит, что в данном месте может стоять один из указанных в скобках символов. Если первый символ в скобках это '^' - значит ни один из указанных символов не может стоять в данном месте выражения. Внутри класса можно употреблять символ '-', обозначающий диапазон символов. Например, a-z - один из малых букв латинского алфавита, 0-9 - цифра и т.д. Все символы, включая специальные, можно обозначать с помощью '\' как в языке С. Альтернативные последовательности разделяются символом '|' Заметьте что внутри квадратных скобок это обычный символ. Внутри регулярного выражения можно указывать "подшаблоны" заключая их в круглые скобки и ссылаться на них как '\номер' Первая скобка обозначается как '\1'.



Пример 3

$var = 1; print $var++ while $var < 5; # Печать $var с инкрементом Результат: 1234
until EXPR- Модификатор "до ". Предложение выполняется до тех пор пока EXPR = false

В данной строке весь фокус!



Пример 4

#!/usr/local/bin/perl open(PASS, "sort -n -t : +3 -4 +0 /etc/passwd|") || die "Файл не найден!"; while(<PASS>) { ($login, $pass, $uid, $gid, $name, $home_dir, $shell) = split(':'); print "$login \t $gid \t $name\n"; } close(PASS); Пояснения:
open(PASS, "sort -n -t : +3 -4 +0 /etc/passwd|") || die "Файл не найден!";

В данной строке весь фокус! Входным файлом для нашей программы стал выход команды sort которая и отсортирует входные данные.
Форматированный вывод.

Ну а теперь напечатаем на экране все наши данные в удобной форме.
#!/usr/local/bin/perl open(PASS, "sort -n -t : +3 -4 +0 /etc/passwd|") || die "Файл не найден!"; while(<PASS>) { ($login, $pass, $uid, $gid, $name, $home_dir, $shell) = split(':'); write(); # Форматированный вывод данных. } close(PASS); exit 0; # Завершение программы ############ Описание формы вывода ################## format STDOUT = Пользователь: ^ Фрагмент результата:
Пользователь: Калужский ликероводочный завод. Лучшие водки и настойки. Звонить только перед праздником Кострикову Анатолию т. 2-23-06,,, ---------------------------------------------------------------------- Login:uucryst Uid:1055 Gid:66 Home dir:/var/spool/uucppublic/ ---------------------------------------------------------------------- Пользователь: Торговый Дом Дилен,,, ---------------------------------------------------------------------- Login:uudilen Uid:1075 Gid:66 Home dir:/var/spool/uucppublic ----------------------------------------------------------------------

Если вам интересно узнать как работает эта программа, то переверните страницу и начините свое путешествие в мире Perl. Желаю удачи!

[Содержание раздела

Пример 4

&sub1, &test_prog, test(12) Имена таблиц символов всегда начинаются символом '*'.
Каждый тип переменных имеет свою область памяти поэтому $var1 и $var1[0] совершенно разные переменные, хотя $var1[0] часть массива @var1. Так же @var1 и %var1 - разные массивы переменных.
Имена переменных могут содержать любые буквенно-цифровые символы за исключением пробела и табуляции. Эти символы используются в качестве разделителей. Большие и малые буквы различаются поэтому $var1 и $Var1 - разные переменные. В Perl по умолчанию имена меток и указателей файлов пишут большими буквами.



Пример 4

reset 'a'; # очистить все переменные начинающиеся # буквой 'a' reset 'a-z' # все переменные с малых букв. Выражение вида: 'A-Z' употреблять не рекомендуется, т.к. обнуляются важные массивы @ARGV и @ENV.



Пример 4

for $i (1..4) { print "$i "; } Результат: 1 2 3 4
В скалярном контексте результат - логическое значение. Каждая '..' операция устанавливает свое собственное состояние. Это false до тех пор пока левый операнд false. Как только левый операнд стал true результат - true до тех пока правый true, после чего результат опять - false. Если вы не хотите проверять правый операнд, то используйте оператор '...'.
Правый операнд не вычисляется пока результат false и левый операнд не вычисляется пока результат true. Приоритетность оператора '..' немного ниже чем '&&' и '||'. Возвращаемое значение если flase - нулевая строка, если true - порядковый номер начиная с 1. Порядковый номер обнуляется для каждого нового диапазона. Последний порядковый номер добавляется строкой "E0" которая не изменяет его значение, но позволяет фиксировать последнее значение.



Пример 4

$var = 1; print $var++ until $var > 5; # Печать $var с инкрементом Результат: 12345
unless EXPR - Модификатор "если не" . Обратный к if. Выражение выполняется если EXPR = false.

Прочитать все строки файла



Пример 5

$var1 = <>; # Прочитать одну строку файла @var1 = <>; # Прочитать все строки файла в массив @var1 $var1 = (1,2,3); # $var = 3 - количество элементов @var1 = (1,2,3); # Создание массива @var1 с элементами 1,2,3


Пример 5

($a, $b, $остаток) = split(/ /, "Один Два Три Четыре",3); здесь $a = 'Один', $b = 'Два' и $остаток = 'Три Четыре'
Если шаблон содержит круглые скобки, то символы-разделители, указанные в них, вставляются в результирующий список как обычные элементы, причем вставляется символ, который совпал с разделителем.



Пример 5

@алфавит = ('a'..'z'); # Массив малых букв латинского алфавита @цифры = (0..9); # Массив цифр



Печать $var

$var = 1; print $var++ unless $var > 5; # Печать $var с инкрементом Результат: 1

Для принудительного получения скалярного значения



Пример 6

@var1 = (4, 3, 2, 1); # Присвоение значения элементам массива $i = @var1; # Использование скалярного контекста print $i; # Печать результата 4 - кол-во элементов print @var1; # Списковый контекст, печать всех элементов. Для принудительного получения скалярного значения удобно применять функцию scalar().


Пример 6

@a = split(/([,.])/, "Один,Два.Три"); здесь @a = ("Один", "," ,"Два", ".", "Три")



Пример 6

$i = 1; $i > 1 ? print "больше" : print "меньше"; Результат: меньше

если существует хотя бы одна



Пример 7

print scalar(@var1); # Вывод длины массива а не его значений Хеш в скалярном контексте возвращает "true", если существует хотя бы одна пара "ключ-значение". Фактически возвращается строка типа 2/8 где 8 - количество выделенных "ячеек" памяти, а 2 - количество использованных.


Пример 7

$a = "/usr/local/perl/perl.bin"; # Анализируемая строка Цель: Создать массив @dirs с именами директорий.
Решение: Самый простой способ воспользоваться split('\/') но в качестве примера используем скобки.
@dirs =~ m[/(\w*)/(\w*)/(\w*)/(\w*)] Здесь 'm[' - использовать квадратные скобки как ограничители. (\w*)- шаблон алфавитно-цифровой последовательности.
В результате @dirs равен ('usr', 'local', 'perl')
q/строка/
'строка'
Строка литералов. Не интерполируется. Внутри строки разрешается использовать \' или \\ для обозначения символов ' и \ .

Обратите внимание на то, что



Пример 8

$var1{first} то же что и $var1{'first'} Обратите внимание на то, что перед первой одинарной кавычкой должен стоять пробел, иначе строка воспримется как имя переменной, т. к. в именах разрешено использование одинарных кавычек. Запрещается в кавычках применять зарезервированные литералы __LINE__ (номер текущей строки программы), __FILE__ (текущий файл). Для обозначения конца программы можно применять литерал __END__ Весь последующий текст игнорируется, но его можно прочитать используя указатель файла DATA.
Слова в программе, не поддающиеся никакой интерпретации, воспринимаются как строки в кавычках, поэтому рекомендуется имена меток и указателей файлов писать большими буквами во избежание возможного "конфликта" с зарезервированными словами.
В Perl есть возможность вставлять текст документа прямо в программу. Так называемый "here-doc" (здесь текст) метод. Обозначается символами << за которыми идет слово-ограничитель.


Пример 8

print q#Привет.#; # Результат Привет. print 'O\'K'; # O'K qq/строка/
"строка"
Интерполируемая строка.

Эй вы трое, идите двое



Пример 9

print <<EOF; # Все строки до EOF - текст для печати. Эй вы трое, идите двое сюда! Что стоишь! Я тебе говорю!! Полковник Савонькин. EOF

Пример 9

$var = 13; print "\$var = $var"; Результат: $var = 13
qx/строка/
`строка`
Сначала строка интерполируется, а потом выполняется как системная команда.



Пример 9

M1: while ($i < 6) { ++$i; # Увеличиваем счетчик на 1 next M1 if $i < 3; # Переходим в начало если $i < 3 ++$i; # иначе увеличиваем счетчик еще раз на 1 } continue { print "$i "; # Печатаем $i } Результат: 1 2 4 6


в списке другие списки, но



Пример 10

@var1 = (1, 2, 'привет', 1.2); # Присвоить значение элементам. где
$var1[0] = 1, $var1[1] = 2, $var1[2] = 'привет' $var1[3] = 1.2 $var1 = (1, 2, 'привет', 1.2); а здесь $var1 = 1.2 т.е. последнее значение списка.
Допускается применять в списке другие списки, но в полученном списке уже невозможно различить начало и конец включенных списков.


Пример 10

print `date`; Результат: Thu Nov 14 13:36:49 MSK 1996
qw/строка/
Возвращает список, элементы которого - слова строки, разделенные пробелами.



Пример 10

M1: while ($i < 6) { ++$i; # Увеличиваем счетчик на 1 last M1 if $i > 3; # Выход из цикла если $i > 3 ++$i; # иначе увеличиваем счетчик еще раз на 1 } continue { print "$i "; # Печатаем $i } Результат: 2 4

Список без элементов обозначается как



Пример 11

@s1 = (1, 2, 3); # Первый список @s2 = (6, 7, 8); # Второй @s = (0, @s1, 4, 5, @s2, 9, 10); # Включаем списки @s1 и @s2 print @s; # Результат: 012345678910 - значения без пробелов. Список без элементов обозначается как () и называется нуль-списком. Списковое выражение можно употреблять как имя массива, но при этом его нужно брать в круглые скобки.


Пример 11

print qw/Построимся и спасемся!/; # ('Построимся','и','спасемся!') Результат:
Построимсяиспасемся! Часто применяется как:
use POSIX qw( setlocale localeconv ) @EXPORT = qw( proc1 var ); s/шаблон/подстрока/egimosx
Поиск по шаблону и в случае успеха замена подстрокой. Возвращает количество произведенных подстановок, иначе false (0). Если строка в которой ведется поиск не указана (операторы =~ или != ), то используется переменная $_ . Если в качестве разделителя '/' использовать одинарную кавычку ('), то интерполяции не будет, иначе можно применять переменные в шаблоне или подстроке.
Опции:
e - Рассматривать правую часть как выражение.
g - Глобальный поиск.
i - Без различия регистра букв
m - многострочная переменная
o - компилировать шаблон один раз
s - однострочная переменная
x - расширенное регулярное выражение
Разделитель '/' можно заменить на любой алфавитно-цифровой символ кроме пробела.



Пример 11

M1: while ($i < 6) { ++$i; # Увеличиваем счетчик на 1 redo M1 if $i == 3; # Далее пропустить для $i = 3 ++$i; # иначе увеличиваем счетчик еще раз на 1 } continue { print "$i "; # Печатаем $i } Результат: 2 5 7

Список может быть присвоен списку



Пример 12

print ('январь','февраль','март')[1]; Результат: февраль
Список может быть присвоен списку только если каждый элемент в списке в левой части выражения допустим по типу списку в правой части.


Пример 12

$var = "12345"; # исходная строка $var =~ s/1/0/; # Заменить '1' на '0'. Результат 02345 $var =~ s(5)(.); # Заменить '5' на '.' Результат 0234. Здесь в качестве разделителя применены скобки, поэтому подстрока взята в две скобки.
$var =~ s/\d*/каламбур/; Заменить все цифры. Результат 'каламбур.' $var =~ s/а/о/g; # Заменить все 'а' на 'о'. Результат 'коломбур.' $var = "12 34"; # Новое значение $var =~ s/(\d\d) (\d\d)/$2 $1/; # Поменять местами числа. Результат '34 12'. tr/таблица1/таблица2/cds
y/таблица1/таблица2/cds
Замена всех символов из "таблица1" на соответствующий символ из "таблица2". Результат - количество замен или стираний. Без оператора =~ или != операция выполняется со строкой $_. Для совместимости с программой sed вместо tr можно писать 'y'.
Опции:
c - дополнение "таблица1"
d - стереть найденные, но не замененные символы.
s - "сжать" повторяющиеся замененные символы.
Если указана опция /d таблица2 всегда интерпретируется как положено. Другими словами, если таблица2 короче, чем таблица1, то символ из таблицы1 интерпретируется всегда. Если таблица2 - null, то все символы строки остаются неизменными. Это удобно для подсчета количества символов в строке определенного класса или для сжатия повторяющихся символов, например, пробелов.



Пример 12

for ($i = 2; $i < 5; ++$i) { print $i, " "; } print "\ nПосле цикла i = $i\n"; Результат:
2 3 4
После цикла i = 5

в скалярном контексте возвращает количество



Пример 13

($a, $b, $c) = (1, 2, 3); # $a = 1, $b = 2, $c = 3 Присваивание списков в скалярном контексте возвращает количество присвоенных элементов.


Пример 13

$s = "hello"; # Исходная строка $s =~ tr/a-z/A-Z/; # Заменить малые буквы на большие. Результат # 'HELLO' $s = 'Hel....lo'; $s =~ tr/a-zA-z/_/c; # Заменить все не буквы на '_' # Результат 'Hel____lo' $s =~ tr/_/ /s; # Заменить '_' на ' ' и сжать. # Результат 'Hel lo' $s =~ tr/a-zA-Z /a-zA-Z/d; # Удалить все не буквы. Результат 'Hello' Если один и тот же символ несколько раз указан в таблице1, то применяется только первая замена.



Пример 13

@месяц = ("январь","февраль","март"); # Создали массив foreach $i (@месяц) { print $i," "; # Печать $i } Результат: январь февраль март

В случае присваивания списка хешу,



Пример 14

$x = (($a, $b, $c) = (1,2)); # Результат $x=2 В случае присваивания списка хешу, список рассматривается как пары: ключ-значение.


Пример 14

while(<>) { print; }; # Прочитать и вывести весь файл STDIN У оператора '<>' есть одна отличительная особенность. Если в командной строке нет никаких аргументов, то читается стандартный ввод, если есть аргументы, то они считаются именами файлов, которые последовательно читаются.
Если в угловых скобках записана переменная, то содержимое этой переменной считается именем указателя файла или ссылкой на указатель файла. Если такого указателя не существует, то содержимое переменной воспринимается как шаблон имен файлов и результат - имена файлов на диске, подходящих по шаблону.



Пример 14

@месяц = ("январь","февраль","март"); # Создали массив foreach $i (@месяц) { $i = uc($i); # Перевели в верхний регистр } print @месяц; Результат: ЯНВАРЬФЕВРАЛЬМАРТ

Для удобства записи можно использовать



Пример 15

%дни_месяца = ('январь', 31, 'февраль', 30); Результат: $дни_месяца{январь} = 31, $дни_месяца{февраль} = 30
Для удобства записи можно использовать выражение с => .


Пример 15

while(<*.pl>) { print;}; # То же что и ls *.pl @files = <*>; # Массив @files содержит имена файлов в директории но лучше сделать: @files = glob("*"); т.к. внутри скобок можно использовать переменные.



Пример 15

for $i (3,5,7) { print "$i "; } Результат: 3 5 7