Spec-Zone.ru › Perl 5.38

perlop

СОДЕРЖАНИЕ

  • НАЗВАНИЕ
  • ОПИСАНИЕ
    • Приоритет и ассоциативность операторов
    • Операторы терминов и списков (слева направо)
    • Оператор стрелки
    • Автоинкремент и автодекремент
    • Возведение в степень
    • Символьные унарные операторы
    • Операторы связывания
    • Мультипликативные операторы
    • Аддитивные операторы
    • Операторы сдвига
    • Именованные унарные операторы
    • Операторы отношений
    • Операторы равенства
    • Оператор экземпляра класса
    • Оператор smartmatch
      • Smartmatch объектов
    • Битовое И
    • Битовое ИЛИ и исключающее ИЛИ
    • Логическое И (стиль C)
    • Логическое ИЛИ (стиль C)
    • Логическое определенное ИЛИ
    • Операторы диапазона
    • Условный оператор
    • Операторы присваивания
    • Оператор запятой
    • Операторы списков (справа налево)
    • Логическое НЕ
    • Логическое И
    • Логическое ИЛИ и исключающее ИЛИ
    • Операторы C, отсутствующие в Perl
    • Операторы кавычек и похожие на них
    • Операторы регулярных выражений, подобные кавычкам
    • Операторы, похожие на кавычки
    • Подробности синтаксического анализа выражений в кавычках
    • Операторы ввода/вывода
    • Сворачивание констант
    • Пустые операторы
    • Битовые строковые операторы
    • Целочисленная арифметика
    • Арифметика с плавающей точкой
    • Более большие числа

НАЗВАНИЕ

perlop - Операторы Perl и их приоритет

ОПИСАНИЕ

В Perl оператор определяет выполняемое действие, независимо от типа операндов. Например, $x + $y всегда является численным сложением, и если $x или $y не содержат чисел, сначала производится попытка преобразовать их в числа.

Это отличается от многих других динамических языков, где операция определяется типом первого аргумента. Это также означает, что Perl имеет два варианта некоторых операторов, один для числового, а другой для строкового сравнения. Например, $x == $y сравнивает два числа на равенство, а $x eq $y сравнивает две строки.

Однако есть несколько исключений: x может быть либо повторением строк, либо повторением списков, в зависимости от типа левого операнда, а &, |, ^ и ~ могут быть либо строковыми, либо числовыми битовыми операциями.

Приоритет и ассоциативность операторов

Приоритет и ассоциативность операторов в Perl работают примерно так же, как и в математике.

Приоритет операторов означает, что некоторые операторы группируют операнды сильнее, чем другие. Например, в 2 + 4 * 5, умножение имеет более высокий приоритет, поэтому 4 * 5 группируется как правый операнд сложения, а не 2 + 4 в качестве левого операнда умножения. Будто выражение было записано как 2 + (4 * 5), а не (2 + 4) * 5. Таким образом, выражение даёт 2 + 20 == 22, а не 6 * 5 == 30.

Ассоциативность операторов определяет, что произойдёт, если используется последовательность одинаковых операторов: обычно они будут группироваться слева направо или справа налево. Например, в 9 - 3 - 2, вычитание левоассоциативно, поэтому 9 - 3 группируется как левый операнд второго вычитания, а не 3 - 2 как правый операнд первого вычитания. Будто выражение было записано как (9 - 3) - 2, а не 9 - (3 - 2). Таким образом, выражение даёт 6 - 2 == 4, а не 9 - 1 == 8.

Для простых операторов, которые оценивают все свои операнды, а затем комбинируют полученные значения каким-то образом, приоритет и ассоциативность (и круглые скобки) предполагают определённый порядок этих комбинирующих операций. Например, в 2 + 4 * 5, группировка, заданная приоритетом, означает, что умножение 4 и 5 должно выполняться до сложения 2 и 20, просто потому, что результат этого умножения необходим в качестве одного из операндов сложения. Но порядок операций не полностью определяется этим: в 2 * 2 + 4 * 5 оба умножения должны выполняться до сложения, но группировка ничего не говорит о порядке выполнения двух умножений. Фактически, Perl имеет общее правило, что операнды оператора вычисляются слева направо. Несколько операторов, таких как &&=, имеют специальные правила вычисления, которые могут привести к тому, что операнд вообще не будет вычислен; в общем случае оператор верхнего уровня в выражении управляет вычислением операндов.

Некоторые операторы сравнения, как и их ассоциативность, цепляются с некоторыми операторами той же приоритетности (но никогда с операторами разного приоритета). Эта цепочка означает, что каждое сравнение выполняется над двумя аргументами, окружающими его, каждый внутренний аргумент участвует в двух сравнениях, а результаты сравнений неявно ANDятся. Таким образом, "$x < $y <= $z" ведёт себя точно так же, как "$x < $y && $y <= $z", предполагая, что "$y" — это простая скалярная переменная. AND также выполняет короткое замыкание, как и "&&", останавливая последовательность сравнений, как только одно из них даёт false.

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

if($x < expensive_sub() <= $z) { ...

не совсем похоже на

if($x < expensive_sub() && expensive_sub() <= $z) { ...

а скорее на

my $tmp = expensive_sub();
if($x < $tmp && $tmp <= $z) { ...

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

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

if ($x < $tied_scalar < $z) { ...

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

if ($x < $tied_scalar + 42 < $z) { ...

Некоторые операторы являются неассоциативными, что означает, что использование последовательности таких операторов одинаковой приоритетности является синтаксической ошибкой. Например, "$x .. $y .. $z" — это ошибка.

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

left	terms and list operators (leftward)
left	->
nonassoc	++ --
right	**
right	! ~ ~. \ and unary + and -
left	=~ !~
left	* / % x
left	+ - .
left	<< >>
nonassoc	named unary operators
nonassoc    isa
chained 	< > <= >= lt gt le ge
chain/na	== != eq ne <=> cmp ~~
left	& &.
left	| |. ^ ^.
left	&&
left	|| //
nonassoc	..  ...
right	?:
right	= += -= *= etc. goto last next redo dump
left	, =>
nonassoc	list operators (rightward)
right	not
left	and
left	or xor

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

Многие операторы могут быть перегружены для объектов. См. overload.

Операторы терминов и списков (слева направо)

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

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

При отсутствии скобок приоритет операторов списков, таких как print, sort, или chmod, очень высок или очень низок в зависимости от того, смотрите ли вы на левую или правую часть оператора. Например, в

@ary = (1, 3, sort 4, 2);
print @ary;		# prints 1324

запятые справа от sort вычисляются до sort, но запятые слева вычисляются после. Другими словами, операторы списков имеют тенденцию поглощать все аргументы, которые следуют за ними, а затем действовать как простой ОПЕРАНД по отношению к предшествующему выражению. Будьте осторожны со скобками:

# These evaluate exit before doing the print:
print($foo, exit);	# Obviously not what you want.
print $foo, exit;	# Nor is this.

# These do the print before evaluating exit:
(print $foo), exit;	# This is what you want.
print($foo), exit;	# Or this.
print ($foo), exit;	# Or even this.

Также обратите внимание, что

print ($foo & 255) + 1, "\n";

вероятно, не сделает того, чего вы ожидаете с первого взгляда. Скобки заключают список аргументов для print, который вычисляется (выводя результат $foo & 255). Затем к возвращаемому значению print (обычно 1) добавляется единица. Результат примерно такой:

1 + 1, "\n";    # Obviously not what you meant.

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

print(($foo & 255) + 1, "\n");

См. "Именованные унарные операторы" для более подробного обсуждения этого.

Также в качестве операндов анализируются конструкции do {} и eval {}, а также вызовы подпрограмм и методов, а также анонимные конструкторы [] и {}.

См. также "Операторы кавычек и подобные кавычкам" в конце этого раздела, а также "Операторы ввода/вывода".

Оператор стрелки

"->" — это инфиксный оператор разыменования, как и в C и C++. Если правая часть — это [...], {...} или индекс (...), то левая часть должна быть либо жёсткой, либо символьной ссылкой на массив, хеш или подпрограмму соответственно. (Или, говоря технически, местоположение, способное хранить жёсткую ссылку, если это ссылка на массив или хеш, используемый для присваивания.) См. perlreftut и perlref.

В противном случае правая часть — это имя метода или простая скалярная переменная, содержащая либо имя метода, либо ссылку на подпрограмму, и (если это имя метода) левая часть должна быть либо объектом (благословенной ссылкой), либо именем класса (то есть именем пакета). См. perlobj.

Случаи разыменования (в отличие от случаев вызова метода) несколько расширены функцией postderef. Для подробностей об этой функции см. "Синтаксис постфиксного разыменования" в perlref.

Автоинкремент и автодекремент

"++" и "--" работают как в C. То есть, если они помещаются перед переменной, они увеличивают или уменьшают переменную на единицу до возвращения значения, а если после — увеличивают или уменьшают после возвращения значения.

$i = 0;  $j = 0;
print $i++;  # prints 0
print ++$j;  # prints 1

Обратите внимание, что, как и в C, Perl не определяет, когда переменная увеличивается или уменьшается. Вы просто знаете, что это будет сделано в какой-то момент до или после возвращения значения. Это также означает, что изменение переменной дважды в одном операторе приведёт к неопределённому поведению. Избегайте операторов вроде:

$i = $i ++;
print ++ $i + $i ++;

Perl не гарантирует результат выполнения вышеперечисленных операторов.

Оператор автоинкремента имеет небольшую встроенную магию. Если вы увеличиваете переменную, которая является числовой или когда-либо использовалась в числовом контексте, вы получаете обычное увеличение. Однако, если переменная использовалась только в строковых контекстах с момента её установки и имеет значение, которое не является пустой строкой и соответствует шаблону /^[a-zA-Z]*[0-9]*\z/, то увеличение выполняется как строковое, сохраняя каждый символ в его диапазоне с переносом:

print ++($foo = "99");	# prints "100"
print ++($foo = "a0");	# prints "a1"
print ++($foo = "Az");	# prints "Ba"
print ++($foo = "zz");	# prints "aaa"

undef всегда обрабатывается как числовой и, в частности, преобразуется в 0 перед увеличением (чтобы постфиксное увеличение значения undef возвращало 0, а не undef).

Оператор автодекремента не является магическим.

Возведение в степень

Бинарный "**" — это оператор возведения в степень. Он связывает даже более жёстко, чем унарный минус, поэтому -2**4 — это -(2**4), а не (-2)**4. (Это реализуется с помощью функции C pow(3), которая фактически работает с числами с плавающей точкой внутри).

Обратите внимание, что некоторые выражения возведения в степень не определены: к ним относятся 0**0, 1**Inf и Inf**0. Не ожидайте каких-либо конкретных результатов от этих специальных случаев; результаты зависят от платформы.

Унарные символьные операторы

Унарный "!" выполняет логическое отрицание, то есть «не». См. также not для версии этого оператора с более низким приоритетом.

Унарный "-" выполняет арифметическое отрицание, если операнд является числовым, включая любые строки, которые выглядят как числа. Если операнд — это идентификатор, возвращается строка, состоящая из знака минус, соединённого с идентификатором. В противном случае, если строка начинается со знака плюс или минус, возвращается строка, начинающаяся с противоположного знака. Одним из эффектов этих правил является то, что -bareword эквивалентно строке "-bareword". Однако, если строка начинается с неалфавитного символа (исключая "+" или "-"), Perl попытается преобразовать строку в числовое значение, и выполняется арифметическое отрицание. Если строку невозможно корректно преобразовать в число, Perl выдаст предупреждение Аргумент "строка" не является числовым в операции отрицания (-) в ....

Унарный "~" выполняет побитовое отрицание, то есть дополнение по модулю 1. Например, 0666 & ~027 равно 0640. (См. также "Целочисленная арифметика" и "Битовые операторы строк"). Обратите внимание, что ширина результата зависит от платформы: ~0 имеет ширину 32 бита на 32-битной платформе, но 64 бита на 64-битной платформе, поэтому, если вы ожидаете определённую ширину бита, помните, что необходимо использовать оператор "&" для маскирования избыточных битов.

Начиная с Perl 5.28, попытка дополнить строку, содержащую символ с порядковым значением выше 255, является фатальной ошибкой.

Если функция «побитовое» включена через use feature 'bitwise' или use v5.28, то унарный "~" всегда обрабатывает свой аргумент как число, а альтернативная форма оператора "~." всегда обрабатывает свой аргумент как строку. Таким образом, ~0 и ~"0" обе дадут 2**32-1 на 32-битных платформах, в то время как ~.0 и ~."0" обе дадут "\xff". До Perl 5.28 эта функция выводила предупреждение в категории "experimental::bitwise".

Унарный "+" не оказывает никакого влияния, даже на строки. Он полезен синтаксически для разделения имени функции от скобочного выражения, которое в противном случае интерпретировалось бы как полный список аргументов функции. (См. примеры выше в "Операторы терминов и списков (влево)").

Унарный "\" создаёт ссылки. Если его операнд — это отдельная сигилированная вещь, он создаёт ссылку на этот объект. Если его операнд — это скобочный список, то он создаёт ссылки на упомянутые вещи в списке. В противном случае он помещает свой операнд в контекст списка и создаёт список ссылок на скаляры в списке, предоставленном операндом. См. perlreftut и perlref. Не путайте это поведение с поведением обратной косой черты внутри строки, хотя обе формы передают понятие защиты следующего элемента от интерполяции.

Операторы привязки

Бинарный "=~" привязывает скалярное выражение к совпадению с шаблоном. Определённые операции ищут или изменяют строку $_ по умолчанию. Этот оператор заставляет такой вид операции работать с какой-то другой строкой. Правый аргумент — это шаблон поиска, подстановка или транслитерация. Левый аргумент — это то, что должно быть найдено, заменено или транслитерировано вместо значения по умолчанию $_. При использовании в скалярном контексте возвращаемое значение, как правило, указывает на успех операции. Исключение составляют подстановка (s///) и транслитерация (y///) с опцией /r (неразрушающая), которые заставляют возвращаемое значение быть результатом подстановки. Поведение в контексте списка зависит от конкретного оператора. См. "Операторы поиска по шаблону, подобные кавычкам" для получения подробностей и perlretut для примеров использования этих операторов.

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

'\\' =~ q'\\';

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

Бинарный "!~" аналогичен "=~", за исключением того, что возвращаемое значение инвертируется в логическом смысле.

Бинарный "!~" с неразрушающей подстановкой (s///r) или транслитерацией (y///r) является синтаксической ошибкой.

Операторы умножения

Бинарный "*" умножает два числа.

Бинарный "/" делит два числа.

Бинарный оператор "%" — это оператор взятия остатка от деления, который вычисляет остаток от деления первого аргумента на второй. При заданных целочисленных операндах $m и $n: Если $n положительно, то $m % $n равно $m минус наибольшее кратное $n, меньшее или равное $m. Если $n отрицательно, то $m % $n равно $m минус наименьшее кратное $n, которое не меньше $m (то есть, результат будет меньше или равен нулю). Если операнды $m и $n — значения с плавающей точкой, а абсолютное значение $n (то есть abs($n)) меньше (UV_MAX + 1), в операции будут использоваться только целые части $m и $n (Примечание: здесь UV_MAX обозначает максимальное значение беззнакового целого типа). Если абсолютное значение правого операнда (abs($n)) больше или равно (UV_MAX + 1), "%" вычисляет остаток с плавающей точкой $r в уравнении ($r = $m - $i*$n), где $i — определённое целое число, которое заставляет $r иметь тот же знак, что и правый операнд $n (не левый операнд $m, как в функции C fmod()), и абсолютное значение меньше, чем у $n. Обратите внимание, что когда use integer активен, "%" даёт прямой доступ к оператору взятия остатка, как он реализован вашим компилятором C. Этот оператор не так хорошо определён для отрицательных операндов, но он будет выполняться быстрее.

Бинарный оператор x — это оператор повторения. В скалярном контексте или если левый операнд не заключён в скобки и не является списком qw//, он выполняет повторение строки. В этом случае он обеспечивает скалярный контекст левому операнду и возвращает строку, состоящую из строки левого операнда, повторяемой количество раз, указанное правым операндом. Если x находится в контексте списка, а левый операнд заключён в скобки или является списком qw//, он выполняет повторение списка. В этом случае он обеспечивает контекст списка левому операнду и возвращает список, состоящий из списка левого операнда, повторяемого количество раз, указанное правым операндом. Если правый операнд равен нулю или отрицателен (выдаётся предупреждение при отрицательном значении), он возвращает пустую строку или пустой список, в зависимости от контекста.

print '-' x 80;		# print row of dashes

print "\t" x ($tab/8), ' ' x ($tab%8);	# tab over

@ones = (1) x 80;		# a list of 80 1's
@ones = (5) x @ones;	# set all elements to 5

Арифметические операторы

Бинарный оператор "+" возвращает сумму двух чисел.

Бинарный оператор "-" возвращает разность двух чисел.

Бинарный оператор "." конкатенирует две строки.

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

Бинарный оператор "<<" возвращает значение своего левого аргумента, сдвинутого влево на количество битов, указанное правым аргументом. Аргументы должны быть целыми числами. (См. также "Целочисленная арифметика".)

Бинарный оператор ">>" возвращает значение своего левого аргумента, сдвинутого вправо на количество битов, указанное правым аргументом. Аргументы должны быть целыми числами. (См. также "Целочисленная арифметика".)

Если use integer (см. "Целочисленная арифметика") активен, используются знакомые целые числа C (арифметический сдвиг), в противном случае используются беззнаковые целые числа C (логический сдвиг), даже для отрицательных операндов. При арифметическом сдвиге вправо знаковый бит дублируется слева, при логическом сдвиге слева добавляются нулевые биты.

В любом случае реализация не будет генерировать результаты, превышающие размер целочисленного типа, с которым был создан Perl (32 бита или 64 бита).

Сдвиг на отрицательное число битов означает обратный сдвиг: сдвиг влево становится сдвигом вправо, сдвиг вправо становится сдвигом влево. Это отличается от C, где отрицательный сдвиг не определён.

Сдвиг на большее количество битов, чем размер целых чисел, чаще всего означает ноль (все биты отпадают), за исключением того, что в условиях use integer при сдвиге вправо отрицательного операнда получается -1. Это отличается от C, где сдвиг на слишком большое количество битов не определён. Общее поведение C — «сдвиг по модулю разрядности слова», так что, например,

1 >> 64 == 1 >> (64 % 64) == 1 >> 0 == 1  # Common C behavior.

но это совершенно случайно.

Если вы устали от подчинения нативным целым числам вашей платформы, pragma use bigint аккуратно обходит эту проблему:

print 20 << 20;  # 20971520
print 20 << 40;  # 5120 on 32-bit machines,
                 # 21990232555520 on 64-bit machines
use bigint;
print 20 << 100; # 25353012004564588029934064107520

Именованные унарные операторы

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

Если за оператором списка (print(), и т. д.) или за любым унарным оператором (chdir(), и т. д.) следует левая круглая скобка как следующий токен, оператор и аргументы в скобках считаются имеющими наивысший приоритет, как и обычный вызов функции. Например, потому что именованные унарные операторы имеют более высокий приоритет, чем ||:

chdir $foo    || die;	# (chdir $foo) || die
chdir($foo)   || die;	# (chdir $foo) || die
chdir ($foo)  || die;	# (chdir $foo) || die
chdir +($foo) || die;	# (chdir $foo) || die

но, потому что "*" имеет более высокий приоритет, чем именованные операторы:

chdir $foo * 20;	# chdir ($foo * 20)
chdir($foo) * 20;	# (chdir $foo) * 20
chdir ($foo) * 20;	# (chdir $foo) * 20
chdir +($foo) * 20;	# chdir ($foo * 20)

rand 10 * 20;	# rand (10 * 20)
rand(10) * 20;	# (rand 10) * 20
rand (10) * 20;	# (rand 10) * 20
rand +(10) * 20;	# rand (10 * 20)

Что касается приоритета, операторы проверки файлов, как -f, -M, и т. д., рассматриваются как именованные унарные операторы, но они не следуют этому правилу с функциональными скобками. Это означает, например, что -f($file).".bak" эквивалентно -f "$file.bak".

См. также "Термы и операторы списков (слева)".

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

Операторы Perl, которые возвращают true или false, обычно возвращают значения, которые безопасно использовать как числа. Например, операторы сравнения в этом разделе и операторы равенства в следующем возвращают 1 для true и специальную версию пустой строки, "", которая считается нулём, но исключена из предупреждений о ненадлежащих числовых преобразованиях, как и "0 but true".

Бинарный оператор "<" возвращает true, если левый аргумент численно меньше правого аргумента.

Бинарный оператор ">" возвращает true, если левый аргумент численно больше правого аргумента.

Бинарный оператор "<=" возвращает true, если левый аргумент численно меньше или равен правому аргументу.

Бинарный оператор ">=" возвращает true, если левый аргумент численно больше или равен правому аргументу.

Бинарный оператор "lt" возвращает true, если левый аргумент лексикографически меньше правого аргумента.

Бинарный оператор "gt" возвращает true, если левый аргумент лексикографически больше правого аргумента.

Бинарный оператор "le" возвращает true, если левый аргумент лексикографически меньше или равен правому аргументу.

Бинарный оператор "ge" возвращает true, если левый аргумент лексикографически больше или равен правому аргументу.

Последовательность операторов сравнения, таких как "$x < $y <= $z", выполняет цепные сравнения, как описано выше в разделе "Приоритет и ассоциативность операторов". Следует быть осторожным, так как они не цепляются к операторам равенства, которые имеют более низкий приоритет.

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

Бинарный оператор "==" возвращает true, если левый аргумент численно равен правому аргументу.

Бинарный оператор "!=" возвращает true, если левый аргумент численно не равен правому аргументу.

Бинарный оператор "eq" возвращает true, если левый аргумент лексикографически равен правому аргументу.

Бинарный оператор "ne" возвращает true, если левый аргумент лексикографически не равен правому аргументу.

Последовательность вышеперечисленных операторов равенства, таких как "$x == $y == $z", выполняет цепные сравнения, как описано выше в разделе "Приоритет и ассоциативность операторов". Следует быть осторожным, так как они не цепляются к операторам сравнения, которые имеют более высокий приоритет.

Бинарный оператор "<=>" возвращает -1, 0 или 1 в зависимости от того, является ли левый аргумент численно меньше, равен или больше правого аргумента. Если ваша платформа поддерживает значения NaN (не числа) как числовые значения, использование их с "<=>" возвращает undef. NaN не является "<", "==", ">", "<=" или ">=" чем-либо (даже NaN), поэтому эти 5 возвращают false. NaN != NaN возвращает true, как и NaN != любое другое значение. Если ваша платформа не поддерживает NaN , то NaN — это просто строка с числовым значением 0.

$ perl -le '$x = "NaN"; print "No NaN support here" if $x == $x'
$ perl -le '$x = "NaN"; print "NaN support here" if $x != $x'

(Обратите внимание, что pragmas bigint, bigrat и bignum все поддерживают "NaN".)

Бинарный оператор "cmp" возвращает -1, 0 или 1 в зависимости от того, является ли левый аргумент лексикографически меньше, равен или больше правого аргумента.

Здесь мы видим разницу между <=> и cmp,

print 10 <=> 2 #prints 1
print 10 cmp 2 #prints -1

(аналогично между gt и >, lt и < и т. д.)

Бинарный оператор "~~" выполняет умное сравнение между своими аргументами. Умное сравнение описано в следующем разделе.

Двусторонние операторы порядка "<=>" и "cmp", а также оператор умного сравнения "~~", не ассоциативны по отношению друг к другу и по отношению к операторам равенства той же приоритетности.

"lt", "le", "ge", "gt" и "cmp" используют порядок сортировки (коллирование), заданный текущим LC_COLLATE локалем, если активна форма use locale, которая включает коллирование. См. perllocale. Не смешивайте их с Unicode, используйте только с кодировками легальных 8-битных локалей. Модули Unicode::Collate и Unicode::Collate::Locale предлагают гораздо более мощные решения проблем коллирования.

Для выполнения сравнений без учёта регистра см. функцию смены регистра "fc" в perlfunc, доступную в Perl v5.16 или более поздних версиях:

if ( fc($x) eq fc($y) ) { ... }

Оператор проверки класса

Бинарный оператор isa оценивается как true, когда левый аргумент является экземпляром класса (или подкласса, полученного от этого класса), заданного правым аргументом. Если левый аргумент не определён, не является экземпляром освящённого объекта или не получен от класса, указанного правым аргументом, оператор оценивается как false. Правый аргумент может передать имя класса либо как идентификатор, либо как выражение скаляра, которое возвращает строковое имя класса:

if( $obj isa Some::Class ) { ... }

if( $obj isa "Different::Class" ) { ... }
if( $obj isa $name_of_class ) { ... }

Эта функция доступна начиная с Perl 5.31.6 при включении use feature 'isa'. Данная функция включается автоматически объявлением use v5.36 (или выше) в текущем области видимости.

Оператор Smartmatch

Впервые доступен в Perl 5.10.1 (версия 5.10.0 имела другое поведение), бинарный ~~ выполняет "умное сравнение" между своими аргументами. Это в основном используется неявно в конструкции when , описанной в perlsyn, хотя не все when предложения используют оператор smartmatch. В отличие от всех остальных операторов Perl, оператор smartmatch может рекурсировать. Оператор smartmatch является экспериментальным и его поведение может быть изменено.

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

Оператор ~~ сравнивает свои операнды "полиморфно", определяя, как их сравнивать, в соответствии с их фактическими типами (числовой, строковый, массив, хеш и т. д.). Как и операторы равенства, с которыми он имеет одинаковый приоритет, ~~ возвращает 1 для истинности и "" для ложности. Его часто лучше произносить вслух как "в", "внутри", или "содержится в", потому что левый операнд часто ищется внутри правого операнда. Это часто меняет порядок операндов по сравнению с обычным оператором сравнения. Другими словами, "меньшая" вещь обычно помещается в левом операнде, а "большая" - в правом.

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

Left      Right      Description and pseudocode
===============================================================
Any       undef      check whether Any is undefined
               like: !defined Any

Any       Object     invoke ~~ overloading on Object, or die

Right operand is an ARRAY:

Left      Right      Description and pseudocode
===============================================================
ARRAY1    ARRAY2     recurse on paired elements of ARRAY1 and ARRAY2[2]
               like: (ARRAY1[0] ~~ ARRAY2[0])
                       && (ARRAY1[1] ~~ ARRAY2[1]) && ...
HASH      ARRAY      any ARRAY elements exist as HASH keys
               like: grep { exists HASH->{$_} } ARRAY
Regexp    ARRAY      any ARRAY elements pattern match Regexp
               like: grep { /Regexp/ } ARRAY
undef     ARRAY      undef in ARRAY
               like: grep { !defined } ARRAY
Any       ARRAY      smartmatch each ARRAY element[3]
               like: grep { Any ~~ $_ } ARRAY

Right operand is a HASH:

Left      Right      Description and pseudocode
===============================================================
HASH1     HASH2      all same keys in both HASHes
               like: keys HASH1 ==
                        grep { exists HASH2->{$_} } keys HASH1
ARRAY     HASH       any ARRAY elements exist as HASH keys
               like: grep { exists HASH->{$_} } ARRAY
Regexp    HASH       any HASH keys pattern match Regexp
               like: grep { /Regexp/ } keys HASH
undef     HASH       always false (undef cannot be a key)
               like: 0 == 1
Any       HASH       HASH key existence
               like: exists HASH->{Any}

Right operand is CODE:

Left      Right      Description and pseudocode
===============================================================
ARRAY     CODE       sub returns true on all ARRAY elements[1]
               like: !grep { !CODE->($_) } ARRAY
HASH      CODE       sub returns true on all HASH keys[1]
               like: !grep { !CODE->($_) } keys HASH
Any       CODE       sub passed Any returns true
               like: CODE->(Any)

Right operand is a Regexp:

Left      Right      Description and pseudocode
===============================================================
ARRAY     Regexp     any ARRAY elements match Regexp
               like: grep { /Regexp/ } ARRAY
HASH      Regexp     any HASH keys match Regexp
               like: grep { /Regexp/ } keys HASH
Any       Regexp     pattern match
               like: Any =~ /Regexp/

Other:

Left      Right      Description and pseudocode
===============================================================
Object    Any        invoke ~~ overloading on Object,
                     or fall back to...

Any       Num        numeric equality
                like: Any == Num
Num       nummy[4]    numeric equality
                like: Num == nummy
undef     Any        check whether undefined
                like: !defined(Any)
Any       Any        string equality
                like: Any eq Any

Примечания:

1. Пустые хеши или массивы совпадают.
2. То есть, каждый элемент smartmatch'ит элемент с тем же индексом в другом массиве.[3]
3. Если обнаружена циклическая ссылка, то возвращается ссылочная эквивалентность.
4. Либо фактическое число, либо строка, похожая на число.

Оператор smartmatch неявно делает dereference любых не-благословенных хешей или массивов, поэтому записи HASH и ARRAY применяются в этих случаях. Для благословенных ссылок применяются записи Object. При smartmatch'е хешей учитываются только ключи хеша, а не значения.

Запись кода "похоже" не всегда является точным воспроизведением. Например, оператор smartmatch по возможности выполняет короткое замыкание, но grep этого не делает. Кроме того, grep в скалярном контексте возвращает количество совпадений, но ~~ возвращает только истину или ложь.

В отличие от большинства операторов, оператор smartmatch знает, как обращаться со undef особым образом:

use v5.10.1;
@array = (1, 2, 3, undef, 4, 5);
say "some elements undefined" if undef ~~ @array;

Каждый операнд рассматривается в измененном скалярном контексте, при этом массивы и хеши передаются оператору по ссылке, который неявно делает dereference.

use v5.10.1;

my %hash = (red    => 1, blue   => 2, green  => 3,
            orange => 4, yellow => 5, purple => 6,
            black  => 7, grey   => 8, white  => 9);

my @array = qw(red blue green);

say "some array elements in hash keys" if  @array ~~  %hash;
say "some array elements in hash keys" if \@array ~~ \%hash;

say "red in array" if "red" ~~  @array;
say "red in array" if "red" ~~ \@array;

say "some keys end in e" if /e$/ ~~  %hash;
say "some keys end in e" if /e$/ ~~ \%hash;

Два массива smartmatch'ятся, если каждый элемент в первом массиве smartmatch'ит (то есть, "в") соответствующий элемент во втором массиве рекурсивно.

use v5.10.1;
my @little = qw(red blue green);
my @bigger = ("red", "blue", [ "orange", "green" ] );
if (@little ~~ @bigger) {  # true!
    say "little is contained in bigger";
}

Поскольку оператор smartmatch рекурсивно применяется к вложенным массивам, это всё ещё сообщит, что "red" содержится в массиве.

use v5.10.1;
my @array = qw(red blue green);
my $nested_array = [[[[[[[ @array ]]]]]]];
say "red in array" if "red" ~~ $nested_array;

Если два массива smartmatch'ятся друг с другом, то они являются глубокими копиями значений друг друга, как сообщает этот пример:

use v5.12.0;
my @a = (0, 1, 2, [3, [4, 5], 6], 7);
my @b = (0, 1, 2, [3, [4, 5], 6], 7);

if (@a ~~ @b && @b ~~ @a) {
    say "a and b are deep copies of each other";
}
elsif (@a ~~ @b) {
    say "a smartmatches in b";
}
elsif (@b ~~ @a) {
    say "b smartmatches in a";
}
else {
    say "a and b don't smartmatch each other at all";
}

Если вы установите $b[3] = 4, то вместо сообщения "a и b являются глубокими копиями друг друга", теперь сообщается, что "b smartmatches in a". Это потому, что соответствующая позиция в @a содержит массив, в котором (в конечном итоге) есть 4.

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

use v5.10.1;
sub make_dogtag {
    state $REQUIRED_FIELDS = { name=>1, rank=>1, serial_num=>1 };

    my ($class, $init_fields) = @_;

    die "Must supply (only) name, rank, and serial number"
        unless $init_fields ~~ $REQUIRED_FIELDS;

    ...
}

Однако, это имеет смысл только если $init_fields действительно является ссылкой на хеш. Условие $init_fields ~~ $REQUIRED_FIELDS также позволяет использовать строки "name", "rank", "serial_num", а также любую ссылку на массив, которая содержит "name" или "rank" или "serial_num" в любом месте, для прохождения.

Оператор smartmatch чаще всего используется в качестве неявного оператора в предложении when. Смотрите раздел "Условные операторы" в perlsyn.

Smartmatch объектов

Чтобы избежать зависимости от внутреннего представления объекта, если правый операнд smartmatch'а является объектом, который не перегружает ~~, он вызывает исключение "Smartmatching a non-overloaded object breaks encapsulation". Это связано с тем, что нет смысла копаться, чтобы увидеть, находится ли что-то "в" объекте. Все это запрещено для объектов без перегрузки ~~:

 %hash ~~ $object
    42 ~~ $object
"fred" ~~ $object

Однако, вы можете изменить способ smartmatch'а объекта, перегрузив оператор ~~. Это позволяет расширить обычные семантики smartmatch. Для объектов, имеющих перегрузку ~~, см. overload.

Использование объекта в качестве левого операнда разрешено, хотя и не очень полезно. Правила smartmatch имеют приоритет над перегрузкой, поэтому даже если объект в левом операнде имеет перегрузку smartmatch, это будет проигнорировано. Левый операнд, являющийся неперегруженным объектом, использует строковое или числовое сравнение того, что возвращает оператор ref. Это означает, что

$object ~~ X

не вызывает метод перегрузки с X в качестве аргумента. Вместо этого используется таблица, как обычно, и на основании типа X, перегрузка может быть или не быть вызвана. Для простых строк или чисел "в" эквивалентно этому:

$object ~~ $number          ref($object) == $number
$object ~~ $string          ref($object) eq $string

Например, это сообщает, что обработчик "пахнет" IOish (но пожалуйста, не делайте этого на самом деле!):

use IO::Handle;
my $fh = IO::Handle->new();
if ($fh ~~ /\bIO\b/) {
    say "handle smells IOish";
}

Потому что он рассматривает $fh как строку, как "IO::Handle=GLOB(0x8039e0)", затем выполняет сопоставление с образцом.

Побитовое И

Бинарный "&" возвращает свои операнды, побитово связанные операцией И. Хотя сейчас предупреждение не выводится, результат не определён, когда эта операция выполняется над операндами, которые не являются числами (см. "Целочисленная арифметика") или битовыми строками (см. "Побитовые строковые операторы").

Обратите внимание, что "&" имеет более низкий приоритет, чем операторы сравнения, поэтому, например, скобки необходимы в таком тесте:

print "Even\n" if ($x & 1) == 0;

Если функция "bitwise" включена через use feature 'bitwise' или use v5.28, то этот оператор всегда рассматривает свои операнды как числа. До Perl 5.28 эта функция выводила предупреждение в категории "experimental::bitwise".

Побитовое Или и Побитовое Исключающее Или

Бинарный "|" возвращает свои операнды, побитово связанные операцией Или.

Бинарный "^" возвращает свои операнды, побитово связанные операцией Исключающее Или.

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

Обратите внимание, что "|" и "^" имеют более низкий приоритет, чем операторы сравнения, поэтому, например, скобки необходимы в таком тесте:

print "false\n" if (8 | 2) != 10;

Если функция "bitwise" включена через use feature 'bitwise' или use v5.28, то этот оператор всегда рассматривает свои операнды как числа. До Perl 5.28 эта функция выводила предупреждение в категории "experimental::bitwise".

Логическое И (стиль C)

Бинарный "&&" выполняет операцию логического И с коротким замыканием. То есть, если левый операнд ложный, правый операнд даже не оценивается. Скалярный или списочный контекст распространяется на правый операнд, если он оценивается.

Логическое Или (стиль C)

Бинарный "||" выполняет операцию логического ИЛИ с коротким замыканием. То есть, если левый операнд истинный, правый операнд даже не оценивается. Скалярный или списочный контекст распространяется на правый операнд, если он оценивается.

Логическое Или (определённость)

Хотя у него нет прямого аналога в C, оператор Perl // связан с его оператором "или" в стиле C. На самом деле, он точно такой же, как ||, за исключением того, что он проверяет определённость левой части, а не её истинность. Таким образом, EXPR1 // EXPR2 возвращает значение EXPR1 , если оно определено; в противном случае возвращается значение EXPR2. (EXPR1 вычисляется в скалярном контексте, EXPR2 в контексте //). Обычно это тот же результат, что и defined(EXPR1) ? EXPR1 : EXPR2 (за исключением того, что форма оператора с тремя операндами может использоваться как lvalue, в то время как EXPR1 // EXPR2 не может). Это очень полезно для предоставления значений по умолчанию для переменных. Если вы хотите проверить, определены ли хотя бы один из $x и $y, используйте defined($x // $y).

Операторы ||, // и && возвращают последнее вычисленное значение (в отличие от C's || и &&, которые возвращают 0 или 1). Таким образом, достаточно переносимый способ определить домашний каталог может быть:

    $home =  $ENV{HOME}
	  // $ENV{LOGDIR}
	  // (getpwuid($<))[7]
	  // die "You're homeless!\n";

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

@a = @b || @c;            # This doesn't do the right thing
@a = scalar(@b) || @c;    # because it really means this.
@a = @b ? @b : @c;        # This works fine, though.

В качестве альтернатив && и || при использовании для управления потоком Perl предоставляет операторы and и or (см. ниже). Поведение короткого замыкания идентично. Однако приоритет "and" и "or" намного ниже, так что вы можете безопасно использовать их после оператора списка без необходимости в скобках:

    unlink "alpha", "beta", "gamma"
	    or gripe(), next LINE;

С операторами в стиле C, которые были бы написаны так:

    unlink("alpha", "beta", "gamma")
	    || (gripe(), next LINE);

Ещё более удобочитаемо было бы написать это так:

unless(unlink("alpha", "beta", "gamma")) {
    gripe();
    next LINE;
}

Использование "or" для присваивания вряд ли сделает то, что вы хотите; см. ниже.

Операторы диапазонов

Бинарный ".." — это оператор диапазона, который фактически представляет собой два разных оператора в зависимости от контекста. В контексте списка он возвращает список значений, считая (с шагом 1) от левого значения до правого. Если левое значение больше правого, то возвращается пустой список. Оператор диапазона полезен для написания foreach (1..10) циклов и для выполнения операций среза над массивами. В текущей реализации при использовании оператора диапазона в качестве выражения в foreach циклах не создаётся временный массив, но более старые версии Perl могут сильно тратить память, если вы напишете что-то вроде этого:

    for (1 .. 1_000_000) {
	# code
    }

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

В скалярном контексте ".." возвращает булево значение. Оператор бистабилен, подобно триггеру, и эмулирует оператор диапазона строк (запятая) из sed, awk и различных редакторов. Каждый ".." оператор сохраняет своё собственное булево состояние, даже при вызовах подпрограммы, содержащей его. Он ложен до тех пор, пока его левый операнд ложен. Как только левый операнд становится истинным, оператор диапазона остаётся истинным до тех пор, пока правый операнд не станет истинным, после чего оператор диапазона вновь становится ложным. Он не становится ложным до следующего вычисления оператора диапазона. Он может проверить правый операнд и стать ложным в том же вычислении, в котором он стал истинным (как в awk), но всё же возвращает истинное значение один раз. Если вы не хотите, чтобы он проверял правый операнд до следующего вычисления, как в sed, используйте три точки ("...") вместо двух. Во всех остальных отношениях, "..." ведёт себя так же, как "..".

Правый операнд не оценивается, пока оператор находится в состоянии «ложь», и левый операнд не оценивается, пока оператор находится в состоянии «истина». Приоритет немного ниже, чем || и &&. Возвращаемое значение — это либо пустая строка для ложного значения, либо порядковый номер (начиная с 1) для истинного значения. Порядковый номер сбрасывается для каждого встреченного диапазона. Конечный порядковый номер в диапазоне имеет строку "E0", добавленную к нему, что не влияет на его числовое значение, но даёт вам что-то, за чем можно искать, если вы хотите исключить конечную точку. Вы можете исключить начальную точку, дождавшись, пока порядковый номер не станет больше 1.

Если любой операнд скалярного ".." — константное выражение, этот операнд считается истинным, если он равен (==) текущему номеру строки ввода (переменная $.).

Для точности, сравнение на самом деле int(EXPR) == int(EXPR), но это проблема только при использовании плавающей точки; при неявном использовании $. как описано в предыдущем абзаце, сравнение — int(EXPR) == int($.), что является проблемой только тогда, когда $. установлено в значение с плавающей точкой и вы не читаете из файла. Кроме того, "span" .. "spat" или 2.18 .. 3.14 не сделают того, что вы хотите в скалярном контексте, потому что каждый из операндов оценивается с использованием своего целочисленного представления.

Примеры:

В качестве скалярного оператора:

if (101 .. 200) { print; } # print 2nd hundred lines, short for
                           #  if ($. == 101 .. $. == 200) { print; }

next LINE if (1 .. /^$/);  # skip header lines, short for
                           #   next LINE if ($. == 1 .. /^$/);
                           # (typically in a loop labeled LINE)

s/^/> / if (/^$/ .. eof());  # quote body

# parse mail messages
while (<>) {
    $in_header =   1  .. /^$/;
    $in_body   = /^$/ .. eof;
    if ($in_header) {
        # do something
    } else { # in body
        # do something else
    }
} continue {
    close ARGV if eof;             # reset $. each file
}

Вот простой пример, чтобы проиллюстрировать разницу между двумя операторами диапазона:

@lines = ("   - Foo",
          "01 - Bar",
          "1  - Baz",
          "   - Quux");

foreach (@lines) {
    if (/0/ .. /1/) {
        print "$_\n";
    }
}

Эта программа будет выводить только строку, содержащую "Bar". Если оператор диапазона изменить на ..., она также выведет строку "Baz".

И теперь несколько примеров в качестве оператора списка:

for (101 .. 200) { print }      # print $_ 100 times
@foo = @foo[0 .. $#foo];        # an expensive no-op
@foo = @foo[$#foo-4 .. $#foo];  # slice last 5 items

Поскольку каждый операнд оценивается в целочисленной форме, 2.18 .. 3.14 вернёт два элемента в контексте списка.

@list = (2.18 .. 3.14); # same as @list = (2 .. 3);

Оператор диапазона в контексте списка может использовать магический алгоритм автоинкремента, если оба операнда являются строками, при соблюдении следующих правил:

  • За одним исключением (ниже), если обе строки похожи на числа для Perl, магический инкремент не будет применён, и строки будут обработаны как числа (точнее, целые числа) вместо этого.

    Например, "-2".."2" равно -2..2, и "2.18".."3.14" даёт 2, 3.

  • Исключение из вышеуказанного правила заключается в том, что если левая строка начинается с 0 и длиннее одного символа, магический инкремент будет применён, даже если строки, подобные "01" обычно воспринимаются Perl как числа.

    Например, "01".."04" даёт "01", "02", "03", "04", и "00".."-1" даёт "00" — "99" - это может показаться неожиданным, но см. следующие правила, объясняющие, почему это работает таким образом. Для получения дат с ведущими нулями можно сказать:

    @z2 = ("01" .. "31");
    print $z2[$mday];

    Если вы хотите принудительно интерпретировать строки как числа, вы можете сказать

    @numbers = ( 0+$first .. 0+$last );

    Примечание: В версиях Perl 5.30 и ниже любая строка слева, начинающаяся с "0", включая строку "0" сама по себе, вызовет магическое поведение инкремента строк. Это означает, что в этих версиях Perl, "0".."-1" даст "0" — "99", что было несовместимо с 0..-1, которое даёт пустой список. Это также означает, что "0".."9" теперь даёт список целых чисел вместо списка строк.

  • Если начальное значение не является частью магической последовательности инкремента (т.е. непустая строка, соответствующая /^[a-zA-Z]*[0-9]*\z/), будет возвращено только начальное значение.

    Например, "ax".."az" даёт "ax", "ay", "az", но "*x".."az" даёт только "*x".

  • Для других начальных значений, которые являются строками, которые следуют правилам магического инкремента, будет возвращена соответствующая последовательность.

    Например, можно сказать

    @alphabet = ("A" .. "Z");

    чтобы получить все обычные буквы английского алфавита, или

    $hexdigit = (0 .. 9, "a" .. "f")[$num & 15];

    чтобы получить шестнадцатеричную цифру.

  • Если конечное значение не входит в последовательность, которую генерирует магический инкремент, последовательность продолжается до тех пор, пока следующее значение не станет длиннее заданного конечного значения. Если длина конечной строки меньше начальной, возвращается пустой список.

    Например, "a".."--" равно "a".."zz", "0".."xx" даёт "0" — "99", и "aaa".."--" возвращает пустой список.

Начиная с Perl 5.26, оператор диапазона в контексте списка со строками работает как ожидается в рамках "use feature 'unicode_strings". В предыдущих версиях и вне этой функции он демонстрирует "Синдром "Unicode-ошибки"" в perlunicode: его поведение зависит от внутреннего кодирования конечной точки диапазона.

Поскольку магический инкремент работает только с непустыми строками, соответствующими /^[a-zA-Z]*[0-9]*\z/, следующее вернёт только альфу:

use charnames "greek";
my @greek_small =  ("\N{alpha}" .. "\N{omega}");

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

use charnames "greek";
my @greek_small =  map { chr } ( ord("\N{alpha}")
                                    ..
                                 ord("\N{omega}")
                               );

Однако, поскольку существует много других строчных греческих символов, помимо тех, для сопоставления строчных греческих символов в регулярном выражении можно использовать шаблон /(?:(?=\p{Greek})\p{Lower})+/ (или экспериментальную функцию /(?[ \p{Greek} & \p{Lower} ])+/).

Условный оператор

Тernary "?:" — условный оператор, как и в C. Он работает примерно как if-then-else. Если аргумент перед ? истинный, возвращается аргумент перед :, иначе — аргумент после :. Например:

    printf "I have %d dog%s.\n", $n,
	    ($n == 1) ? "" : "s";

Скалярный или списочный контекст распространяется вниз на 2-й или 3-й аргумент, какой из них выбран.

$x = $ok ? $y : $z;  # get a scalar
@x = $ok ? @y : @z;  # get an array
$x = $ok ? @y : @z;  # oops, that's just a count!

Оператор можно присвоить, если и 2-й, и 3-й аргументы являются допустимыми lvalue (то есть можно присваивать им значение):

($x_or_y ? $x : $y) = $z;

Поскольку этот оператор производит присваиваемое значение, использование присваиваний без скобок приведёт к проблемам. Например, это:

$x % 2 ? $x += 10 : $x += 2

На самом деле означает это:

(($x % 2) ? ($x += 10) : $x) += 2

Вместо этого:

($x % 2) ? ($x += 10) : ($x += 2)

Это лучше записать проще:

$x += ($x % 2) ? 10 : 2;

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

"=" — обычный оператор присваивания.

Операторы присваивания работают как в C. То есть,

$x += 2;

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

$x = $x + 2;

хотя без дублирования любых побочных эффектов, которые может вызвать разыменование lvalue, таких как от tie(). Аналогично работают и другие операторы присваивания. Признаются следующие:

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

Хотя они сгруппированы по семействам, все они имеют приоритет присваивания. Эти комбинированные операторы присваивания могут работать только со скалярами, в то время как обычный оператор присваивания может присваивать значения массивам, хешам, спискам и даже ссылкам. (См. "Контекст" и "Конструкторы списковых значений" в perldata и "Присваивание ссылкам" в perlref.)

В отличие от C, скалярный оператор присваивания производит допустимое lvalue. Изменение присваивания эквивалентно выполнению присваивания, а затем изменению переменной, которой было присвоено значение. Это полезно для изменения копии чего-либо, как в этом примере:

($tmp = $global) =~ tr/13579/24680/;

Хотя начиная с версии 5.14, это можно также сделать так:

use v5.14;
$tmp = ($global =~  tr/13579/24680/r);

Аналогично,

($x += 2) *= 3;

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

$x += 2;
$x *= 3;

Точно так же, присваивание списка в контексте списка производит список присвоенных lvalue, а присваивание списка в скалярном контексте возвращает количество элементов, производимых выражением в правой части присваивания.

Три оператора битового присваивания с точкой (&.= |.= ^.=) являются новыми в Perl 5.22. См. "Операторы битового сравнения строк".

Оператор запятой

Бинарный "," — это оператор запятой. В скалярном контексте он оценивает свой левый аргумент, отбрасывает это значение, затем оценивает свой правый аргумент и возвращает это значение. Это точно так же, как оператор запятой в C.

В контексте списка это просто разделитель аргументов списка и добавляет оба своих аргумента в список. Эти аргументы также оцениваются слева направо.

Оператор => (иногда произносится как «толстая запятая») — это синоним запятой, за исключением того, что он заставляет слово слева интерпретироваться как строка, если оно начинается с буквы или подчёркивания и состоит только из букв, цифр и подчёркиваний. Это включает операнды, которые в противном случае могли бы интерпретироваться как операторы, константы, строковые значения с одной цифрой или вызовы функций. Если вы сомневаетесь в этом поведении, можно явно привести левый операнд к строке.

В противном случае оператор => ведёт себя точно так же, как оператор запятой или разделитель аргументов списка в зависимости от контекста.

Например:

use constant FOO => "something";

my %h = ( FOO => 23 );

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

my %h = ("FOO", 23);

А НЕ:

my %h = ("something", 23);

Оператор => полезен для документирования соответствия между ключами и значениями в хэшах и других парных элементах в списках.

%hash = ( $key => $value );
login( $username => $password );

Особое поведение цитирования игнорирует приоритет и, следовательно, может применяться к части левого операнда:

print time.shift => "bbb";

Этот пример выводит что-то вроде "1314363215shiftbbb", потому что => неявно цитирует shift непосредственно слева, игнорируя тот факт, что time.shift является целым левым операндом.

Операторы списков (правосторонние)

С правой стороны оператора списка запятая имеет очень низкий приоритет, так что она управляет всеми выражениями, разделенными запятыми, которые там находятся. Единственными операторами с более низким приоритетом являются логические операторы "and", "or", и "not", которые могут быть использованы для оценки вызовов операторов списка без необходимости в скобках:

open HANDLE, "< :encoding(UTF-8)", "filename"
    or die "Can't open: $!\n";

Однако некоторые люди считают, что такой код сложнее читать, чем писать его со скобками:

open(HANDLE, "< :encoding(UTF-8)", "filename")
    or die "Can't open: $!\n";

в этом случае вы можете просто использовать более привычный оператор "||":

open(HANDLE, "< :encoding(UTF-8)", "filename")
    || die "Can't open: $!\n";

См. также обсуждение операторов списков в "Операторы списков и терминов (левосторонние)".

Логическое отрицание

Унарный "not" возвращает логическое отрицание выражения справа от него. Это эквивалентно "!", за исключением очень низкого приоритета.

Логическое И

Бинарный "and" возвращает логическое конъюнкцию двух окружающих выражений. Это эквивалентно &&, за исключением очень низкого приоритета. Это означает, что он выполняет короткую цепочку: правое выражение оценивается только в том случае, если левое выражение истинно.

Логическое ИЛИ и исключающее ИЛИ

Бинарный "or" возвращает логическое дизъюнкцию двух окружающих выражений. Это эквивалентно ||, за исключением очень низкого приоритета. Это делает его полезным для управления потоком:

print FH $data		or die "Can't write to FH: $!";

Это означает, что он выполняет короткую цепочку: правое выражение оценивается только в том случае, если левое выражение ложно. Из-за своего приоритета вы должны быть осторожны, чтобы избежать его использования в качестве замены оператора ||. Обычно он лучше работает для управления потоком, чем в присваиваниях:

$x = $y or $z;              # bug: this is wrong
($x = $y) or $z;            # really means this
$x = $y || $z;              # better written this way

Однако, когда это присваивание в контексте списка, и вы пытаетесь использовать || для управления потоком, вам, вероятно, нужен "or", чтобы присваивание имело более высокий приоритет.

@info = stat($file) || die;     # oops, scalar sense of stat!
@info = stat($file) or die;     # better, now @info gets its due

Впрочем, вы всегда можете использовать скобки.

Бинарный "xor" возвращает исключающее ИЛИ двух окружающих выражений. Он не может выполнять короткую цепочку (конечно).

Нет оператора с низким приоритетом для определенного ИЛИ.

Операторы C, отсутствующие в Perl

Вот что есть у C, но нет у Perl:

унарный &

Оператор адреса. (Но см. оператор "\" для получения ссылки.)

унарный *

Оператор разыменования адреса. (Префиксные операторы разыменования Perl имеют тип: $, @, %, и &.)

(TYPE)

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

Операторы кавычек и похожие на кавычки

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

    Customary  Generic        Meaning	     Interpolates
	''	 q{}	      Literal		  no
	""	qq{}	      Literal		  yes
	``	qx{}	      Command		  yes*
		qw{}	     Word list		  no
	//	 m{}	   Pattern match	  yes*
		qr{}	      Pattern		  yes*
		 s{}{}	    Substitution	  yes*
		tr{}{}	  Transliteration	  no (but see below)
		 y{}{}	  Transliteration	  no (but see below)
        <<EOF                 here-doc            yes*

	* unless the delimiter is ''.

Разделители, не являющиеся скобками, используют один и тот же символ спереди и сзади, но четыре типа ASCII-скобок (круглые, угловые, квадратные, фигурные) все вложены, что означает, что

q{foo{bar}baz}

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

'foo{bar}baz'

Однако, это не всегда работает для цитирования кода Perl:

$s = q{ if($x eq "}") ... }; # WRONG

является синтаксической ошибкой. Модуль Text::Balanced (стандартный начиная с v5.8 и из CPAN до этого) может сделать это правильно.

Между оператором и символами кавычек может (и в некоторых случаях должен) быть пробел, за исключением случаев, когда # используется в качестве символа кавычек. q#foo# парсится как строка foo, в то время как q #foo# является оператором q и комментарием. Его аргумент будет взят со следующей строки. Это позволяет вам написать:

s {foo}  # Replace foo
  {bar}  # with bar.

Случаи, когда пробелы должны быть использованы, возникают, когда символ кавычки является буквенным символом (что означает, что он соответствует /\w/):

q XfooX # Works: means the string 'foo'
qXfooX  # WRONG!

Следующие escape-последовательности доступны в конструкциях, которые интерполируются, и в транслитерациях, разделители которых не являются одинарными кавычками ("'"). Во всех конструкциях с фигурными скобками допускается любое количество пробелов и/или табуляции, прилегающих к и внутри фигурных скобок (и они игнорируются).

Sequence     Note  Description
\t                  tab               (HT, TAB)
\n                  newline           (NL)
\r                  return            (CR)
\f                  form feed         (FF)
\b                  backspace         (BS)
\a                  alarm (bell)      (BEL)
\e                  escape            (ESC)
\x{263A}     [1,8]  hex char          (example shown: SMILEY)
\x{ 263A }          Same, but shows optional blanks inside and
                    adjoining the braces
\x1b         [2,8]  restricted range hex char (example: ESC)
\N{name}     [3]    named Unicode character or character sequence
\N{U+263D}   [4,8]  Unicode character (example: FIRST QUARTER MOON)
\c[          [5]    control char      (example: chr(27))
\o{23072}    [6,8]  octal char        (example: SMILEY)
\033         [7,8]  restricted range octal char  (example: ESC)

Обратите внимание, что любая escape-последовательность, использующая фигурные скобки внутри интерполированных конструкций, может иметь необязательные пробелы (символы табуляции или пробела), прилегающие к и внутри фигурных скобок, как показано выше на втором примере \x{ }.

[1]

Результат — символ, задаваемый шестнадцатеричным числом в фигурных скобках. Подробности о том, какой символ будет, см. в "[8]" ниже.

Пробелы (табуляция или пробелы) могут отделять число от фигурных скобок.

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

Если между фигурными скобками нет допустимых цифр, генерируемый символ — это нулевой символ (\x{00}). Однако явное пустое фигурная скобка (\x{}) не вызовет предупреждения (на данный момент).

[2]

Результат — символ, задаваемый шестнадцатеричным числом в диапазоне от 0x00 до 0xFF. Подробности о том, какой символ будет, см. в "[8]" ниже.

После \x допустимы только шестнадцатеричные цифры. Когда \x следует меньше двух допустимых цифр, любые допустимые цифры будут дополнены нулями. Это означает, что \x7 будет интерпретировано как \x07, а одиночное "\x" будет интерпретировано как \x00. За исключением конца строки, наличие менее двух допустимых цифр приведет к предупреждению. Обратите внимание, что, хотя предупреждение говорит о том, что недопустимый символ игнорируется, он игнорируется только как часть экранирования и по-прежнему будет использоваться в качестве последующего символа в строке. Например:

Original    Result    Warns?
"\x7"       "\x07"    no
"\x"        "\x00"    no
"\x7q"      "\x07q"   yes
"\xq"       "\x00q"   yes
[3]

Результат — символ Unicode или последовательность символов, заданные с помощью name. См. charnames.

[4]

\N{U+hexadecimal number} означает символ Unicode, кодовый точка которого — шестнадцатеричное число.

[5]

Символ, следующий за \c, отображается в некотором другом символе, как показано в таблице:

Sequence   Value
  \c@      chr(0)
  \cA      chr(1)
  \ca      chr(1)
  \cB      chr(2)
  \cb      chr(2)
  ...
  \cZ      chr(26)
  \cz      chr(26)
  \c[      chr(27)
                    # See below for chr(28)
  \c]      chr(29)
  \c^      chr(30)
  \c_      chr(31)
  \c?      chr(127) # (on ASCII platforms; see below for link to
                    #  EBCDIC discussion)

Другими словами, это символ, кодовый точка которого имеет 64 побитовое исключающее ИЛИ со своим верхним регистром. \c? — это DELETE на платформах ASCII, потому что ord("?") ^ 64 равно 127, а \c@ — NULL, потому что ord от "@" равно 64, поэтому побитовое исключающее ИЛИ 64 само по себе дает 0.

Также \c\X даст chr(28) . "X" для любого X, но не может стоять в конце строки, потому что обратная косая черта была бы интерпретирована как экранирование заключительной кавычки.

На платформах ASCII результирующие символы из приведенного выше списка составляют полный набор управляющих символов ASCII. Это не так на платформах EBCDIC; см. "OPERATOR DIFFERENCES" в perlebcdic для полного обсуждения различий между этими значениями для платформ ASCII и EBCDIC.

Использование любых других символов после "c" кроме перечисленных выше не рекомендуется, и, начиная с Perl v5.20, единственными разрешенными символами на самом деле являются печатные символы ASCII, минус левая фигурная скобка "{". Что происходит для любого из разрешенных других символов, так это то, что значение выводится путем побитового исключающего ИЛИ с седьмым битом, который равен 64, и выводится предупреждение, если оно включено. Использование недопустимых символов приводит к фатальной ошибке.

Для получения платформонезависимых управляющих символов можно использовать \N{...}.

[6]

Результат — символ, задаваемый восьмеричным числом в фигурных скобках. Подробности о том, какой символ будет, см. в "[8]" ниже.

Пробелы (табуляция или пробелы) могут отделять число от фигурных скобок.

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

[7]

Результат — символ, задаваемый трехзначным восьмеричным числом в диапазоне от 000 до 777 (но лучше не использовать значения выше 077, см. следующий абзац). Подробности о том, какой символ будет, см. в "[8]" ниже.

В некоторых контекстах допускается 2 или даже 1 цифра, но любое использование без ровно трех цифр, первой из которых является ноль, может дать непредвиденные результаты. (Например, в регулярном выражении это может быть спутано со ссылкой на обратную ссылку; см. "Octal escapes" в perlrebackslash.) Начиная с Perl 5.14, можно использовать \o{}, что избегает всех этих проблем. В противном случае лучше всего использовать эту конструкцию только для порядковых номеров \077 и ниже, помня о необходимости дополнения нулями слева, чтобы получить три цифры. Для больших порядковых номеров используйте \o{}, или преобразуйте в что-то другое, например, в шестнадцатеричное и используйте \N{U+} (что переносимо между платформами с разными наборами символов) или \x{} вместо этого.

[8]

Несколько конструкций выше указывают символ по числу. Это число соответствует позиции символа в кодировке набора символов (индексируется с 0). Это также называется порядковым номером, позицией кода или кодовым точкой. Perl работает на платформах, которые в настоящее время имеют родную кодировку ASCII/Latin1 или EBCDIC, каждая из которых позволяет указать 256 символов. В общем, если число меньше или равно 255 (0xFF, 0377), Perl интерпретирует это в родной кодировке платформы. Если число больше или равно 256 (0x100, 0400), Perl интерпретирует его как кодовую точку Unicode, и результат — соответствующий символ Unicode. Например, \x{50} и \o{120} оба представляют число 80 в десятичной системе, которое меньше 256, поэтому число интерпретируется в родной кодировке набора символов. В ASCII символ в 80-й позиции (индексируется с 0) — это буква "P", а в EBCDIC — символ амперсанда "&". \x{100} и \o{400} оба равны 256 в десятичной системе, поэтому число интерпретируется как кодовая точка Unicode независимо от родной кодировки. Имя символа в 256-й позиции (индексируется с 0) в Unicode — LATIN CAPITAL LETTER A WITH MACRON.

Исключение из приведенного выше правила состоит в том, что \N{U+hex number} всегда интерпретируется как кодовая точка Unicode, поэтому \N{U+0050} является "P" даже на платформах EBCDIC.

ПРИМЕЧАНИЕ: В отличие от C и других языков, Perl не имеет \v последовательности экранирования для вертикальной табуляции (VT, которая равна 11 как в ASCII, так и в EBCDIC), но можно использовать \N{VT}, \N{U+0b}, \x0b, или \x0b. (\v имеет значение в шаблонах регулярных выражений в Perl, см. perlre.)

Следующие последовательности экранирования доступны в конструкциях, которые выполняют интерполяцию, но не в транслитерациях.

    \l		lowercase next character only
    \u		titlecase (not uppercase!) next character only
    \L		lowercase all characters till \E or end of string
    \U		uppercase all characters till \E or end of string
    \F		foldcase all characters till \E or end of string
    \Q          quote (disable) pattern metacharacters till \E or
                end of string
    \E		end either case modification or quoted section
		(whichever was last seen)

См. "quotemeta" в perlfunc для точного определения символов, которые экранируются с помощью \Q.

\L, \U, \F, и \Q могут быть вложены, в таком случае вам потребуется один \E для каждого. Например:

say "This \Qquoting \ubusiness \Uhere isn't quite\E done yet,\E is it?";
This quoting\ Business\ HERE\ ISN\'T\ QUITE\ done\ yet\, is it?

Если активна форма use locale, которая включает LC_CTYPE, (см. perllocale), преобразование регистров, используемое \l, \L, \u, и \U, берется из текущего языка. Если используется Unicode (например, \N{} или кодовые точки 0x100 и выше), преобразование регистров, используемое \l, \L, \u, и \U, определяется Unicode. Это означает, что преобразование регистра одиночного символа иногда может давать последовательность нескольких символов. В подсистеме use locale \F дает те же результаты, что и \L для всех языков, кроме UTF-8, где вместо этого используется определение Unicode.

Все системы используют виртуальный "\n" для представления символа конца строки, называемого «новая строка». Нет такого символа, как неизменный физический символ конца строки. Это всего лишь иллюзия, которую поддерживают операционная система, драйверы устройств, библиотеки C и Perl. Не все системы читают "\r" как ASCII CR и "\n" как ASCII LF. Например, на старых компьютерах Macintosh (до MacOS X) эти символы использовались в обратном порядке, а на системах без символа конца строки печать "\n" могла не генерировать никаких данных. В общем, используйте "\n" когда нужно «новая строка» для вашей системы, но используйте буквальные ASCII символы, когда нужен точный символ. Например, большинство сетевых протоколов ожидают и предпочитают CR+LF ("\015\012" или "\cM\cJ") в качестве символов конца строки, и хотя они часто принимают только "\012", они редко терпят только "\015". Если вы привыкнете использовать "\n" для работы в сети, вы можете столкнуться с проблемами в будущем.

Для конструкций, которые интерполируют переменные, начинающиеся с «$» или «@» интерполируются. Интерполируются также индексированные переменные, такие как $a[3] или $href->{key}[0], а также фрагменты массивов и хэшей. Но вызовы методов, такие как $obj->meth, не интерполируются.

Интерполяция массива или среза интерполирует элементы в порядке, разделенные значением $", что эквивалентно интерполяции join $", @array. Массивы «знаков препинания», такие как @*, обычно интерполируются только в том случае, если имя заключено в фигурные скобки @{*}, но массивы @_, @+, и @- интерполируются даже без фигурных скобок.

Для строк в двойных кавычках экранирование от \Q применяется после интерполяции и обработки экранирования.

"abc\Qfoo\tbar$s\Exyz"

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

"abc" . quotemeta("foo\tbar$s") . "xyz"

Для шаблона операторов регулярных выражений (qr//, m// и s///) экранирование от \Q применяется после обработки интерполяции, но перед обработкой экранирования. Это позволяет шаблону соответствовать буквально (за исключением $ и @). Например, следующее совпадает:

'\s\t' =~ /\Q\s\t/

Поскольку $ или @ вызывают интерполяцию, вам потребуется что-то вроде /\Quser\E\@\Qhost/ для соответствия им буквально.

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

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

Операторы экранирования для регулярных выражений

Вот операторы экранирования, которые применяются к сопоставлению с образцом и смежным действиям.

qr/STRING/msixpodualn

Этот оператор цитирует (и, возможно, компилирует) свой STRING как регулярное выражение. STRING интерполируется так же, как PATTERN в m/PATTERN/. Если "'" используется в качестве разделителя, интерполяция переменных не выполняется. Возвращает значение Perl, которое может использоваться вместо соответствующего /STRING/msixpodualn выражения. Возвращаемое значение — это нормализованная версия исходного шаблона. Оно магически отличается от строки, содержащей те же символы: ref(qr/x/) возвращает "Regexp"; однако обращение к нему не определено (сейчас вы получаете нормализованную версию исходного шаблона, но это может измениться).

Например,

$rex = qr/my.STRING/is;
print $rex;                 # prints (?si-xm:my.STRING)
s/$rex/foo/;

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

s/my.STRING/foo/is;

Результат может быть использован как подшаблон в соответствии:

$re = qr/$pattern/;
$string =~ /foo${re}bar/;	# can be interpolated in other
                            # patterns
$string =~ $re;		# or used standalone
$string =~ /$re/;		# or this way

Так как Perl может скомпилировать шаблон в момент выполнения оператора qr(), использование qr() может иметь преимущества в скорости в некоторых ситуациях, особенно если результат qr() используется автономно:

    sub match {
	my $patterns = shift;
	my @compiled = map qr/$_/i, @$patterns;
	grep {
	    my $success = 0;
	    foreach my $pat (@compiled) {
		$success = 1, last if /$pat/;
	    }
	    $success;
	} @_;
    }

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

Параметры (указанные следующими модификаторами) являются:

m	Treat string as multiple lines.
s	Treat string as single line. (Make . match a newline)
i	Do case-insensitive pattern matching.
x   Use extended regular expressions; specifying two
    x's means \t and the SPACE character are ignored within
    square-bracketed character classes
p	When matching preserve a copy of the matched string so
    that ${^PREMATCH}, ${^MATCH}, ${^POSTMATCH} will be
    defined (ignored starting in v5.20 as these are always
    defined starting in that release)
o	Compile pattern only once.
a   ASCII-restrict: Use ASCII for \d, \s, \w and [[:posix:]]
    character classes; specifying two a's adds the further
    restriction that no ASCII character will match a
    non-ASCII one under /i.
l   Use the current run-time locale's rules.
u   Use Unicode rules.
d   Use Unicode or native charset, as in 5.12 and earlier.
n   Non-capture mode. Don't let () fill in $1, $2, etc...

Если предварительно скомпилированный шаблон встроен в более крупный шаблон, то эффект "msixpluadn" будет распространяться соответствующим образом. Эффект, который имеет модификатор /o, не распространяется, будучи ограниченным теми шаблонами, которые его явно используют.

Модификаторы /a, /d, /l, и /u (добавлены в Perl 5.14) управляют правилами набора символов, но /a — единственный, который, вероятно, захотите указать явно; остальные три выбираются автоматически различными предикатами.

См. perlre для получения дополнительной информации о допустимом синтаксисе для STRING и для подробного ознакомления с семантикой регулярных выражений. В частности, все модификаторы, за исключением в значительной степени устаревшего /o, подробно описаны в "Modifiers" in perlre. /o описан в следующем разделе.

m/PATTERN/msixpodualngc
/PATTERN/msixpodualngc

Ищет в строке совпадение с шаблоном и в скалярном контексте возвращает true, если поиск успешен, и false, если нет. Если строка не указана с помощью оператора =~ или !~, то ищется строка $_. (Строка, указанная с =~, не обязательно должна быть lvalue — она может быть результатом вычисления выражения, но помните, что =~ связывает достаточно плотно.) См. также perlre.

Параметры описаны в qr// выше; кроме того, доступны следующие модификаторы процесса сопоставления:

g  Match globally, i.e., find all occurrences.
c  Do not reset search position on a failed match when /g is
   in effect.

Если "/" — разделитель, то начальный m является необязательным. С помощью m вы можете использовать любую пару не-пробельных (ASCII) символов в качестве разделителей. Это особенно полезно для сопоставления имен путей, содержащих "/", чтобы избежать синдрома LTS (наклоненной зубочистки). Если "?" является разделителем, то применяется правило сопоставления только один раз, описанное в m?PATTERN? ниже. Если "'" (одинарная кавычка) — разделитель, интерполяция переменных в PATTERN не выполняется. При использовании символа-разделителя, допустимого в идентификаторе, после m требуется пробел.

PATTERN может содержать переменные, которые будут интерполироваться каждый раз, когда оценивается поиск по шаблону, за исключением случаев, когда разделитель — одинарная кавычка. (Обратите внимание, что $(, $), и $| не интерполируются, потому что они выглядят как тесты на конец строки.) Perl не будет перекомпилировать шаблон, если интерполируемая переменная в нём изменяется. Вы можете заставить Perl пропустить проверку и никогда не перекомпилировать, добавив /o (что означает «один раз») после заключительного разделителя. Когда-то Perl излишне перекомпилировал регулярные выражения, и этот модификатор был полезен, чтобы сказать ему этого не делать, в интересах скорости. Но сейчас единственные причины для использования /o следующие:

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

  2. Вы хотите, чтобы шаблон использовал начальные значения переменных независимо от того, изменяются они или нет. (Но есть более разумные способы достижения этого, чем использование /o.)

  3. Если шаблон содержит вложенный код, например

    use re 'eval';
    $code = 'foo(?{ $x })';
    /$code/

    тогда Perl будет перекомпилировать каждый раз, даже если строка шаблона не изменилась, чтобы убедиться, что текущее значение $x отображается каждый раз. Используйте /o если вы хотите избежать этого.

В итоге использование /o почти никогда не является хорошей идеей.

Пустой шаблон //

Если PATTERN оценивается как пустая строка, используется последний успешно сопоставленный регулярный шаблон. В этом случае учитываются только флаги g и c пустого шаблона; другие флаги берутся из исходного шаблона. Если ранее ни одно сопоставление не было успешным, это будет (бесшумно) действовать как настоящий пустой шаблон (который всегда будет соответствовать). Использование предоставленной пользователем строки в качестве шаблона имеет риск, что если строка пустая, это вызовет поведение «последнего успешного соответствия», что может быть очень запутанным. В таких случаях рекомендуется заменить m/$pattern/ на m/(?:$pattern)/, чтобы избежать этого поведения.

Последний успешный шаблон можно получить как переменную через ${^LAST_SUCCESSFUL_PATTERN}. Сопоставление с ним или с пустым шаблоном должно иметь тот же эффект, за исключением того, что когда нет последнего успешного шаблона, пустой шаблон будет бесшумно соответствовать, в то время как использование переменной ${^LAST_SUCCESSFUL_PATTERN} вызовет предупреждения об неопределённости (если включены предупреждения). Вы можете проверить defined(${^LAST_SUCCESSFUL_PATTERN}) , чтобы проверить, есть ли «последнее успешное соответствие» в текущей области.

Обратите внимание, что Perl можно запутать, заставив его подумать, что // (пустой regex) на самом деле является // (оператором «или, если определено»). Perl обычно справляется с этим хорошо, но некоторые патологические случаи могут вызвать это, такие как $x/// (это ($x) / (//) или $x // /?) и print $fh // (print $fh(// или print($fh //?). Во всех этих примерах Perl предположит, что вы имели в виду «или, если определено». Если вы имели в виду пустой regex, просто используйте скобки или пробелы, чтобы снять неоднозначность, или даже префикс пустого regex с m (так // становится m//).

Сопоставление в списочном контексте

Если опция /g не используется, m// в списочном контексте возвращает список, состоящий из подвыражений, сопоставленных скобками в шаблоне, то есть ($1, $2, $3...) (Обратите внимание, что здесь также устанавливаются $1 и т.д.). Когда в шаблоне нет скобок, возвращаемое значение — список (1) при успехе. С скобками или без, пустой список возвращается при неудаче.

Примеры:

open(TTY, "+</dev/tty")
   || die "can't access /dev/tty: $!";

<TTY> =~ /^y/i && foo();	# do foo if desired

if (/Version: *([0-9.]*)/) { $version = $1; }

next if m#^/usr/spool/uucp#;

# poor man's grep
$arg = shift;
while (<>) {
   print if /$arg/o; # compile only once (no longer needed!)
}

if (($F1, $F2, $Etc) = ($foo =~ /^(\S+)\s+(\S+)\s*(.*)/))

Этот последний пример разбивает $foo на первые два слова и оставшуюся часть строки, а эти три поля присваиваются $F1, $F2, и $Etc. Условное выражение истинно, если какие-либо переменные были присвоены, то есть шаблон соответствовал.

Модификатор /g определяет глобальное сопоставление с шаблоном — то есть сопоставление как можно большее количество раз в строке. Как он себя ведёт, зависит от контекста. В списочном контексте он возвращает список подстрок, сопоставленных с любыми захватывающими скобками в регулярном выражении. Если скобок нет, он возвращает список всех сопоставленных строк, как если бы вокруг всего шаблона были скобки.

В скалярном контексте каждое выполнение m//g находит следующее соответствие, возвращая true, если оно соответствует, и false, если больше нет соответствий. Позицию после последнего сопоставления можно прочитать или установить с помощью функции pos(); см. "pos" in perlfunc. Неудачное сопоставление обычно сбрасывает позицию поиска к началу строки, но вы можете этого избежать, добавив модификатор /c (например, m//gc). Изменение целевой строки также сбрасывает позицию поиска.

\G assertion

Вы можете смешивать сопоставления m//g с m/\G.../g, где \G — утверждение нулевой ширины, которое соответствует точной позиции, где предыдущее m//g, если таковое было, остановилось. Без модификатора /g, утверждение \G всё ещё привязывается к pos() как в начале операции (см. "pos" in perlfunc), но сопоставление, конечно, предпринимается только один раз. Использование \G без /g в целевой строке, к которой ранее не применялось соответствие /g, равносильно использованию утверждения \A для сопоставления начала строки. Обратите также внимание, что в настоящее время \G должным образом поддерживается только при привязке к самому началу шаблона.

Примеры:

    # list context
    ($one,$five,$fifteen) = (`uptime` =~ /(\d+\.\d+)/g);

    # scalar context
    local $/ = "";
    while ($paragraph = <>) {
	while ($paragraph =~ /\p{Ll}['")]*[.!?]+['")]*\s/g) {
	    $sentences++;
	}
    }
    say $sentences;

Вот ещё один способ проверить предложения в абзаце:

my $sentence_rx = qr{
   (?: (?<= ^ ) | (?<= \s ) )  # after start-of-string or
                               # whitespace
   \p{Lu}                      # capital letter
   .*?                         # a bunch of anything
   (?<= \S )                   # that ends in non-
                               # whitespace
   (?<! \b [DMS]r  )           # but isn't a common abbr.
   (?<! \b Mrs )
   (?<! \b Sra )
   (?<! \b St  )
   [.?!]                       # followed by a sentence
                               # ender
   (?= $ | \s )                # in front of end-of-string
                               # or whitespace
}sx;
local $/ = "";
while (my $paragraph = <>) {
   say "NEW PARAGRAPH";
   my $count = 0;
   while ($paragraph =~ /($sentence_rx)/g) {
       printf "\tgot sentence %d: <%s>\n", ++$count, $1;
   }
}

Вот как использовать m//gc с \G:

$_ = "ppooqppqq";
while ($i++ < 2) {
    print "1: '";
    print $1 while /(o)/gc; print "', pos=", pos, "\n";
    print "2: '";
    print $1 if /\G(q)/gc;  print "', pos=", pos, "\n";
    print "3: '";
    print $1 while /(p)/gc; print "', pos=", pos, "\n";
}
print "Final: '$1', pos=",pos,"\n" if /\G(.)/;

Последний пример должен вывести:

1: 'oo', pos=4
2: 'q', pos=5
3: 'pp', pos=7
1: '', pos=7
2: 'q', pos=8
3: '', pos=8
Final: 'q', pos=8

Заметьте, что последнее сопоставление сопоставилось с q вместо p, что сделало бы сопоставление без якоря \G. Также обратите внимание, что последнее сопоставление не обновило pos. pos обновляется только при сопоставлении /g. Если последнее соответствие действительно сопоставилось с p, то, вероятно, вы используете древнюю (до 5.6.0) версию Perl.

Полезный идиоматический способ для сканеров, похожих на lex, — /\G.../gc. Вы можете комбинировать несколько regexps таким образом, чтобы обрабатывать строку по частям, выполняя разные действия в зависимости от того, какой regexp сопоставился. Каждый regexp пытается сопоставиться с тем местом, где закончился предыдущий.

$_ = <<'EOL';
   $url = URI::URL->new( "http://example.com/" );
   die if $url eq "xXx";
EOL

LOOP: {
    print(" digits"),       redo LOOP if /\G\d+\b[,.;]?\s*/gc;
    print(" lowercase"),    redo LOOP
                                   if /\G\p{Ll}+\b[,.;]?\s*/gc;
    print(" UPPERCASE"),    redo LOOP
                                   if /\G\p{Lu}+\b[,.;]?\s*/gc;
    print(" Capitalized"),  redo LOOP
                             if /\G\p{Lu}\p{Ll}+\b[,.;]?\s*/gc;
    print(" MiXeD"),        redo LOOP if /\G\pL+\b[,.;]?\s*/gc;
    print(" alphanumeric"), redo LOOP
                           if /\G[\p{Alpha}\pN]+\b[,.;]?\s*/gc;
    print(" line-noise"),   redo LOOP if /\G\W+/gc;
    print ". That's all!\n";
}

Вот вывод (разбит на несколько строк):

line-noise lowercase line-noise UPPERCASE line-noise UPPERCASE
line-noise lowercase line-noise lowercase line-noise lowercase
lowercase line-noise lowercase lowercase line-noise lowercase
lowercase line-noise MiXeD line-noise. That's all!
m?PATTERN?msixpodualngc

Это аналогично оператору m/PATTERN/, но он выполняет сопоставление только один раз между вызовами оператора reset(). Это полезная оптимизация, когда вы хотите увидеть только первое вхождение чего-либо в каждом файле из набора файлов, например. Только шаблоны m??, локальные для текущего пакета, сбрасываются.

    while (<>) {
	if (m?^$?) {
			    # blank line between header and body
	}
    } continue {
	reset if eof;	    # clear m?? status for next file
    }

Другой пример переключал первое найденное кодирование «latin1» на «utf8» в файле pod:

s//utf8/ if m? ^ =encoding \h+ \K latin1 ?x;

Поведение сопоставления один раз контролируется разделителем сопоставления, который равен ?; с любым другим разделителем это обычный оператор m//.

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

s/PATTERN/REPLACEMENT/msixpodualngcer

Ищет в строке шаблон и, если он найден, заменяет этот шаблон текстом замены и возвращает количество произведённых замещений. В противном случае возвращает false (значение, которое является как пустой строкой (""), так и численным нулём (0) как описано в "Операторы сравнения").

Если используется опция /r (неразрушающая), то она выполняет замену на копии строки и вместо возвращения количества замещений возвращает копию, независимо от того, произошла ли замена. Исходная строка никогда не изменяется при использовании /r. Копия всегда будет обычной строкой, даже если вход является объектом или связанной переменной.

Если строка не указана с помощью операторов =~ или !~, то ищется и изменяется переменная $_. Если не используется опция /r, указанная строка должна быть скалярной переменной, элементом массива, элементом хэша или присвоением одному из них; другими словами, некоторая скалярная переменная-лев.

Если выбранный разделитель — одинарная кавычка, то интерполяция переменных не выполняется ни для PATTERN, ни для REPLACEMENT. В противном случае, если PATTERN содержит $, похожее на переменную, а не на тест конца строки, переменная будет интерполирована в шаблон во время выполнения. Если вы хотите, чтобы шаблон компилировался только один раз при первой интерполяции переменной, используйте опцию /o. Если шаблон вычисляется как пустая строка, используется последний успешно выполненный регулярный шаблон. См. perlre для дополнительного объяснения.

Опции те же, что и для оператора m//, с добавлением следующих опций, специфичных для замены:

e	Evaluate the right side as an expression.
ee  Evaluate the right side as a string then eval the
    result.
r   Return substitution and leave the original string
    untouched.

Любой разделитель, отличный от пробела, может заменить косые черты. Добавьте пробел после s, если используется символ, разрешённый в идентификаторах. Если используются одинарные кавычки, никакой интерпретации строки замены не выполняется (однако модификатор /e переопределяет это). Обратите внимание, что Perl обрабатывает обратные кавычки как обычные разделители; текст замены не оценивается как команда. Если PATTERN ограничен скобочными кавычками, у REPLACEMENT есть своя пара кавычек, которые могут быть или не быть скобочными кавычками, например, s(foo)(bar) или s<foo>/bar/. /e приведет к тому, что часть замены будет обработана как полноценное выражение Perl и вычислена прямо на месте. Однако она проверяется на синтаксические ошибки на этапе компиляции. Второй модификатор e вызовет eval части замены перед её выполнением как выражения Perl.

Примеры:

    s/\bgreen\b/mauve/g;	      # don't change wintergreen

    $path =~ s|/usr/bin|/usr/local/bin|;

    s/Login: $foo/Login: $bar/; # run-time pattern

    ($foo = $bar) =~ s/this/that/;	# copy first, then
                                        # change
    ($foo = "$bar") =~ s/this/that/;	# convert to string,
                                        # copy, then change
    $foo = $bar =~ s/this/that/r;	# Same as above using /r
    $foo = $bar =~ s/this/that/r
                =~ s/that/the other/r;	# Chained substitutes
                                        # using /r
    @foo = map { s/this/that/r } @bar	# /r is very useful in
                                        # maps

    $count = ($paragraph =~ s/Mister\b/Mr./g);  # get change-cnt

    $_ = 'abc123xyz';
    s/\d+/$&*2/e;		# yields 'abc246xyz'
    s/\d+/sprintf("%5d",$&)/e;	# yields 'abc  246xyz'
    s/\w/$& x 2/eg;		# yields 'aabbcc  224466xxyyzz'

    s/%(.)/$percent{$1}/g;	# change percent escapes; no /e
    s/%(.)/$percent{$1} || $&/ge;	# expr now, so /e
    s/^=(\w+)/pod($1)/ge;	# use function call

    $_ = 'abc123xyz';
    $x = s/abc/def/r;           # $x is 'def123xyz' and
                                # $_ remains 'abc123xyz'.

    # expand variables in $_, but dynamics only, using
    # symbolic dereferencing
    s/\$(\w+)/${$1}/g;

    # Add one to the value of any numbers in the string
    s/(\d+)/1 + $1/eg;

    # Titlecase words in the last 30 characters only (presuming
    # that the substring doesn't start in the middle of a word)
    substr($str, -30) =~ s/\b(\p{Alpha})(\p{Alpha}*)\b/\u$1\L$2/g;

    # This will expand any embedded scalar variable
    # (including lexicals) in $_ : First $1 is interpolated
    # to the variable name, and then evaluated
    s/(\$\w+)/$1/eeg;

    # Delete (most) C comments.
    $program =~ s {
	/\*	# Match the opening delimiter.
	.*?	# Match a minimal number of characters.
	\*/	# Match the closing delimiter.
    } []gsx;

    s/^\s*(.*?)\s*$/$1/;	# trim whitespace in $_,
                                # expensively

    for ($variable) {		# trim whitespace in $variable,
                                # cheap
	s/^\s+//;
	s/\s+$//;
    }

    s/([^ ]*) *([^ ]*)/$2 $1/;	# reverse 1st two fields

    $foo !~ s/A/a/g;    # Lowercase all A's in $foo; return
                        # 0 if any were found and changed;
                        # otherwise return 1

Обратите внимание на использование $ вместо \ в последнем примере. В отличие от sed, мы используем форму \<цифра> только в левой части. В любом другом месте это $<цифра>.

Иногда для получения всех желаемых изменений недостаточно просто использовать /g. Вот два распространённых случая:

# put commas in the right places in an integer
1 while s/(\d)(\d\d\d)(?!\d)/$1,$2/g;

# expand tabs to 8-column spacing
1 while s/\t+/' ' x (length($&)*8 - length($`)%8)/e;

Хотя s/// принимает флаг /c, он не оказывает никакого воздействия, кроме как выдачи предупреждения, если включены предупреждения.

Операторы-в-стиле-кавычек

q/STRING/
'STRING'

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

$foo = q!I said, "You said, 'She said it.'"!;
$bar = q('This is it.');
$baz = '\n';		# a two-character string
qq/STRING/
"STRING"

Интерполированная строка в двойных кавычках.

    $_ .= qq
     (*** The previous line contains the naughty word "$1".\n)
		if /\b(tcl|java|python)\b/i;      # :-)
    $baz = "\n";		# a one-character string
qx/STRING/
`STRING`

Строка, которая (возможно) интерполируется, а затем выполняется как системная команда через /bin/sh или его эквивалент, если это необходимо. Будут учтены командные символы, pipes и перенаправления. Аналогично system, если строка не содержит командных метасимволов, то она будет выполнена непосредственно. Возвращается собранный стандартный вывод команды; стандартная ошибка не затрагивается. В скалярном контексте он возвращается как одна (возможно, многострочная) строка или undef, если оболочка (или команда) не могла быть запущена. В контексте списка возвращается список строк (как вы определили строки с $/ или $INPUT_RECORD_SEPARATOR) или пустой список, если оболочка (или команда) не могла быть запущена.

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

$output = `cmd 2>&1`;

Для захвата стандартного вывода команды, но отбрасывания её стандартной ошибки:

$output = `cmd 2>/dev/null`;

Для захвата стандартной ошибки команды, но отбрасывания её стандартного вывода (порядок важен здесь):

$output = `cmd 2>&1 1>/dev/null`;

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

$output = `cmd 3>&1 1>&2 2>&3 3>&-`;

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

system("program args 1>program.stdout 2>program.stderr");

Дескриптор файла STDIN, используемый командой, наследуется от STDIN Perl. Например:

open(SPLAT, "stuff")   || die "can't open stuff: $!";
open(STDIN, "<&SPLAT") || die "can't dupe SPLAT: $!";
print STDOUT `sort`;

выведет отсортированное содержимое файла с именем «stuff».

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

$perl_info  = qx(ps $$);            # that's Perl's $$
$shell_info = qx'ps $$';            # that's the new shell's $$

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

На некоторых платформах (особенно похожих на DOS), оболочка может не иметь возможности обрабатывать многострочные команды, поэтому вставка новых строк в строку может не дать желаемого результата. Вы можете оценить несколько команд в одной строке, разделив их символом разделителя команд, если ваша оболочка поддерживает это (например, ; во многих оболочках Unix и & в оболочке Windows NT cmd).

Perl попытается очистить все файлы, открытые для вывода, перед запуском дочернего процесса, но это может быть не поддерживаемо на некоторых платформах (см. perlport). Для безопасности может потребоваться установить $| ($AUTOFLUSH в English или вызвать метод autoflush() объекта IO::Handle на всех открытых дескрипторах.

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

Использование этого оператора может привести к программам, которые трудно портировать, потому что вызываемые командные строки отличаются в разных системах и, возможно, вообще отсутствуют. Например, команда type в оболочке POSIX сильно отличается от команды type в DOS. Это не означает, что нужно избегать обратных кавычек, когда они являются правильным способом что-то сделать. Perl предназначен для того, чтобы быть языком-связкой, и одним из способов связки является связывание команд. Просто поймите, во что вы ввязываетесь.

Как и в случае с system, обратные кавычки помещают код возврата дочернего процесса в $?. Если вы хотите вручную проверить ошибки, вы можете проверить все возможные режимы ошибок, проверив $? следующим образом:

if ($? == -1) {
    print "failed to execute: $!\n";
}
elsif ($? & 127) {
    printf "child died with signal %d, %s coredump\n",
        ($? & 127),  ($? & 128) ? 'with' : 'without';
}
else {
    printf "child exited with value %d\n", $? >> 8;
}

Используйте прагму open, чтобы управлять слоями ввода-вывода при чтении вывода команды, например:

use open IN => ":encoding(UTF-8)";
my $x = `cmd-producing-utf-8`;

qx// также может вызываться как функция с помощью "readpipe" в perlfunc.

См. "Операторы ввода-вывода" для дополнительного обсуждения.

qw/STRING/

Возвращает список слов, извлечённых из STRING, используя встроенные пробелы в качестве разделителей слов. Это можно рассматривать как примерно эквивалентное:

split(" ", q/STRING/);

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

qw(foo bar baz)

семантически эквивалентно списку:

"foo", "bar", "baz"

Некоторые часто встречающиеся примеры:

use POSIX qw( setlocale localeconv )
@EXPORT = qw( foo bar baz );

Распространённой ошибкой является попытка разделить слова запятыми или вставить комментарии в многострочную строку qw. По этой причине прагма use warnings и переключатель -w (то есть переменная $^W) выдают предупреждения, если STRING содержит символы "," или "#".

tr/SEARCHLIST/REPLACEMENTLIST/cdsr
y/SEARCHLIST/REPLACEMENTLIST/cdsr

Транслитерирует все вхождения символов, найденных (или не найденных, если указан модификатор /c) в списке поиска, на соответствующий по позиции символ в списке замены, возможно, удаляя некоторые символы в зависимости от указанных модификаторов. Возвращает количество заменённых или удалённых символов. Если строка не указана с помощью оператора =~ или !~, транслируется строка $_.

Для поклонников sed, y предоставляется как синоним для tr.

Если присутствует опция /r (неразрушающая), создаётся новая копия строки, и символы в ней транслируются, и эта копия возвращается независимо от того, была ли она изменена или нет: исходная строка всегда остаётся неизменной. Новая копия всегда является обычной строкой, даже если исходная строка является объектом или привязанной переменной.

За исключением случая использования опции /r, строка, указанная с помощью =~, должна быть скалярной переменной, элементом массива, элементом хеша или присваиванием одному из них; другими словами, lvalue.

Символы, разделяющие СПИСОК_ПОИСКА и СПИСОК_ЗАМЕНЫ, могут быть любым печатным символом, а не только прямым слэшем. Если это одиночные кавычки (tr'SEARCHLIST'REPLACEMENTLIST'), единственная интерполяция заключается в удалении \ из пар \\; поэтому дефисы интерпретируются буквально, а не указывают диапазон символов.

В противном случае диапазон символов может быть указан с помощью дефиса, поэтому tr/A-J/0-9/ выполняет ту же замену, что и tr/ACEGIBDFHJ/0246813579/.

Если СПИСОК_ПОИСКА ограничен кавычками, СПИСОК_ЗАМЕНЫ должен иметь свою пару кавычек, которые могут быть или не быть кавычками; например, tr(aeiouy)(yuoiea) или tr[+\-*/]"ABCD". Этот последний пример демонстрирует способ наглядного разъяснения происходящего для людей, более знакомых с шаблонами регулярных выражений, чем с tr, и которые могут думать, что разделители слэша подразумевают, что tr больше похож на шаблон регулярного выражения, чем это на самом деле. (Другим вариантом может быть использование tr[...][...].)

tr не полностью подобно скобочным классам символов, а (значительно) больше похоже на них, чем на полные шаблоны. Например, символы, появляющиеся более одного раза в любом списке, ведут себя по-другому здесь, чем в шаблонах, и списки tr не допускают классов символов со слэшем, таких как \d или \pL, а также интерполяции переменных, поэтому "$" и "@" всегда обрабатываются как литералы.

Разрешённые элементы — литералы плюс \' (означающие одиночную кавычку). Если разделители не являются одиночными кавычками, также разрешены любые из последовательностей escape, принимаемых в строках с двойными кавычками. Подробности последовательностей escape находятся в таблице в начале этого раздела.

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

Оператор tr не эквивалентен утилите tr(1). tr[a-z][A-Z] преобразует 26 букв от «a» до «z» в верхний регистр, но для изменения регистра, не ограничиваясь ASCII, используйте lc, uc, lcfirst, ucfirst (все документированы в perlfunc), или оператор подстановки s/PATTERN/REPLACEMENT/ (с \U, \u, \L, и \l escape-последовательностями интерполяции строк в части ЗАМЕНА).

Большинство диапазонов непереносимы между наборами символов, но некоторые из них сигнализируют Perl о выполнении специальной обработки, чтобы сделать их переносимыми. Существует два класса переносимых диапазонов. Первый — любые подмножества диапазонов A-Z, a-z, и 0-9, когда они выражены как литеральные символы.

tr/h-k/H-K/

преобразует в верхний регистр буквы "h", "i", "j", и "k", и ничего более, независимо от набора символов платформы. В отличие от этого, все

tr/\x68-\x6B/\x48-\x4B/
tr/h-\x6B/H-\x4B/
tr/\x68-k/\x48-K/

выполняют те же преобразования в верхний регистр, что и предыдущий пример, при выполнении на платформах ASCII, но что-то совершенно другое на платформах EBCDIC.

Второй класс переносимых диапазонов вызывается, когда один или оба конечных точки диапазона выражены как \N{...}

$string =~ tr/\N{U+20}-\N{U+7E}//d;

удаляет из $string все символы платформы, которые эквивалентны любому из Unicode U+0020, U+0021, ... U+007D, U+007E. Это переносимый диапазон, и он имеет тот же эффект на каждой платформе, на которой он выполняется. В этом примере это печатные символы ASCII. Итак, после выполнения этого, $string содержит только управляющие символы и символы, у которых нет эквивалентов ASCII.

Однако даже для переносимых диапазонов обычно не очевидно, что включено, не взглянув в руководство. Звучащим принципом является использование только диапазонов, которые начинаются и заканчиваются либо ASCII буквами одинакового регистра (b-e, B-E), или цифрами (1-4). Все остальное неясно (и непереносимо, если не используется \N{...}). В случае сомнений, полностью запишите наборы символов.

Опции:

    c	Complement the SEARCHLIST.
    d	Delete found but unreplaced characters.
    r	Return the modified string and leave the original string
	untouched.
    s	Squash duplicate replaced characters.

Если указан модификатор /d, любые символы, указанные в СПИСКЕ_ПОИСКА, не найденные в СПИСКЕ_ЗАМЕНЫ, удаляются. (Обратите внимание, что это немного более гибко, чем поведение некоторых программ tr, которые удаляют всё, что находят в СПИСКЕ_ПОИСКА, без исключений.)

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

my $a = "aaabbbca";
$a =~ tr/ab/dd/s;     # $a now is "dcd"

Если используется модификатор /d, СПИСОК_ЗАМЕНЫ всегда интерпретируется точно как указано. В противном случае, если СПИСОК_ЗАМЕНЫ короче, чем СПИСОК_ПОИСКА, последний символ, если он есть, дублируется до тех пор, пока он не станет достаточно длинным. Конечного символа не будет тогда и только тогда, когда СПИСОК_ЗАМЕНЫ пустой, в этом случае СПИСОК_ЗАМЕНЫ копируется из СПИСОК_ПОИСКА. Пустой СПИСОК_ЗАМЕНЫ полезен для подсчёта символов в классе или для сжатия последовательностей символов в классе.

tr/abcd//            tr/abcd/abcd/
tr/abcd/AB/          tr/abcd/ABBB/
tr/abcd//d           s/[abcd]//g
tr/abcd/AB/d         (tr/ab/AB/ + s/[cd]//g)  - but run together

Если указан модификатор /c, символы, которые должны быть транслированы, — это символы, НЕ находящиеся в СПИСКЕ_ПОИСКА, то есть, он дополняется. Если /d и/или /s также указаны, они применяются к дополненному СПИСКЕ_ПОИСКА. Помните, что если СПИСОК_ЗАМЕНЫ пустой (кроме случаев с /d), он копируется из СПИСОК_ПОИСКА. Эта копия создаётся после дополнения под действием /c. СПИСОК_ПОИСКА сортируется по кодовой точке после дополнения, и любой СПИСОК_ЗАМЕНЫ применяется к этому отсортированному результату. Это означает, что при /c, порядок символов, указанных в СПИСКЕ_ПОИСКА, не имеет значения. Это может привести к различным результатам на системах EBCDIC, если СПИСОК_ЗАМЕНЫ содержит более одного символа, поэтому использование /c с таким СПИСОК_ЗАМЕНЫ, как правило, не является переносимым.

Другой способ описать операцию: Если /c указано, СПИСОК_ПОИСКА сортируется по кодовой точке, затем дополняется. Если СПИСОК_ЗАМЕНЫ пустой, и /d не указано, СПИСОК_ЗАМЕНЫ заменяется копией СПИСОК_ПОИСКА (как изменённого под действием /c), и эти потенциально изменённые списки используются в качестве основы для того, что следует дальше. Любой символ в целевой строке, который не находится в СПИСКЕ_ПОИСКА, передаётся без изменений. Каждый другой символ в целевой строке заменяется символом в СПИСКЕ_ЗАМЕНЫ, который по позиции соответствует его пару в СПИСКЕ_ПОИСКА, за исключением того, что при /s, второй и последующие символы выжимаются в последовательности символов в ряд, которые все переводятся в один и тот же символ. Если СПИСОК_ПОИСКА длиннее, чем СПИСОК_ЗАМЕНЫ, символы в целевой строке, которые соответствуют символу в СПИСКЕ_ПОИСКА, у которого нет соответствия в СПИСКЕ_ЗАМЕНЫ, либо удаляются из целевой строки, если /d указано; или заменяются последним символом в СПИСКЕ_ЗАМЕНЫ, если /d не указано.

Некоторые примеры:

$ARGV[1] =~ tr/A-Z/a-z/;   # canonicalize to lower case ASCII

$cnt = tr/*/*/;            # count the stars in $_
$cnt = tr/*//;             # same thing

$cnt = $sky =~ tr/*/*/;    # count the stars in $sky
$cnt = $sky =~ tr/*//;     # same thing

$cnt = $sky =~ tr/*//c;    # count all the non-stars in $sky
$cnt = $sky =~ tr/*/*/c;   # same, but transliterate each non-star
                           # into a star, leaving the already-stars
                           # alone.  Afterwards, everything in $sky
                           # is a star.

$cnt = tr/0-9//;           # count the ASCII digits in $_

tr/a-zA-Z//s;              # bookkeeper -> bokeper
tr/o/o/s;                  # bookkeeper -> bokkeeper
tr/oe/oe/s;                # bookkeeper -> bokkeper
tr/oe//s;                  # bookkeeper -> bokkeper
tr/oe/o/s;                 # bookkeeper -> bokkopor

($HOST = $host) =~ tr/a-z/A-Z/;
 $HOST = $host  =~ tr/a-z/A-Z/r; # same thing

$HOST = $host =~ tr/a-z/A-Z/r   # chained with s///r
              =~ s/:/ -p/r;

tr/a-zA-Z/ /cs;                 # change non-alphas to single space

@stripped = map tr/a-zA-Z/ /csr, @original;
                                # /r with map

tr [\200-\377]
   [\000-\177];                 # wickedly delete 8th bit

$foo !~ tr/A/a/    # transliterate all the A's in $foo to 'a',
                   # return 0 if any were found and changed.
                   # Otherwise return 1

Если для одного символа даётся несколько транслирований, используется только первое:

tr/AAA/XYZ/

будет транслировать любой A в X.

Поскольку таблица транслирования строится во время компиляции, ни СПИСОК_ПОИСКА, ни СПИСОК_ЗАМЕНЫ не подвергаются интерполяции двойных кавычек. Это означает, что если вы хотите использовать переменные, вы должны использовать eval().

eval "tr/$oldlist/$newlist/";
die $@ if $@;

eval "tr/$oldlist/$newlist/, 1" or die $@;
<<EOF

Строковая форма цитирования основана на синтаксисе оболочки «here-document». После << вы указываете строку для завершения цитируемого материала, и все строки, следующие за текущей строкой до строки завершения, являются значением элемента.

Префикс строки завершения ~ указывает, что вы хотите использовать "Утопленные Here-документы" (см. ниже).

Строка завершения может быть либо идентификатором (словом), либо какой-либо цитированной строкой. Нецитированный идентификатор работает так же, как двойные кавычки. Между << и идентификатором не должно быть пробела, если идентификатор не цитирован явно. Строка завершения должна появляться сама по себе (без кавычек и без окружающего пробела) в строке завершения.

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

Двойные кавычки

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

   print <<EOF;
The price is $Price.
EOF

   print << "EOF"; # same as above
The price is $Price.
EOF
Одинарные кавычки

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

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

	$cost = <<'VISTA';  # hasta la ...
    That'll be $10 please, ma'am.
    VISTA

	$cost = <<\VISTA;   # Same thing!
    That'll be $10 please, ma'am.
    VISTA

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

Обратные кавычки

Содержимое here-документа обрабатывается так же, как если бы строка была вставлена в обратные кавычки. Таким образом, содержимое интерполируется так, как если бы оно было в двойных кавычках, а затем выполняется через оболочку, и результат выполнения возвращается.

   print << `EOC`; # execute command and get results
echo hi there
EOC
Утопленные Here-документы

Модификатор here-документа ~ позволяет вам вставлять отступы в ваши here-документы, чтобы сделать код более читабельным:

if ($some_var) {
  print <<~EOF;
    This is a here-doc
    EOF
}

Это будет выведено...

This is a here-doc

...без ведущего пробела.

Строка, содержащая разделитель, обозначающий конец here-документа, определяет шаблон отступа для всего here-документа. Компиляция завершается ошибкой, если любая ненулевая строка внутри here-документа не начинается с точного отступа строки завершения. (Пустая строка состоит из единственного символа «\n».) Например, предположим, что строка завершения начинается с символа табуляции, за которым следуют 4 пробела. Каждая ненулевая строка в here-документе должна начинаться с табуляции, за которой следуют 4 пробела. Они удаляются из каждой строки, и любой оставшийся ведущий пробел в строке служит отступом для этой строки. В настоящее время в качестве пробела для этой цели рассматриваются только символы TAB и SPACE. Табы и пробелы могут быть смешаны, но точно соответствуют; табы остаются табами и не расширяются.

Дополнительный начальный пробел (сверх того, что предшествовал разделителю) будет сохранён:

print <<~EOF;
  This text is not indented
    This text is indented with two spaces
  		This text is indented with two tabs
  EOF

Наконец, модификатор может быть использован со всеми вышеупомянутыми формами:

<<~\EOF;
<<~'EOF'
<<~"EOF"
<<~`EOF`

И пробелы могут быть использованы между ~ и цитируемыми разделителями:

<<~ 'EOF'; # ... "EOF", `EOF`

Можно размещать несколько here-документов подряд:

   print <<"foo", <<"bar"; # you can stack them
I said foo.
foo
I said bar.
bar

   myfunc(<< "THIS", 23, <<'THAT');
Here's a line
or two.
THIS
and here's another.
THAT

Просто не забудьте поставить точку с запятой в конце, чтобы завершить оператор, так как Perl не знает, что вы не собираетесь это сделать:

   print <<ABC
179231
ABC
   + 20;

Если вы хотите удалить символы новой строки из своих here-документов, используйте chomp().

chomp($string = <<'END');
This is a string.
END

Если вы хотите, чтобы ваши here-документы были отформатированы с отступом, соответствующим остальному коду, используйте конструкцию <<~FOO , описанную в разделе "Утопленные Here-документы":

$quote = <<~'FINIS';
   The Road goes ever on and on,
   down from the door where it began.
   FINIS

Если вы используете here-документ внутри ограниченной конструкции, например, в s///eg, цитируемый материал должен всё ещё находиться в строке, следующей за меткой <<FOO, что означает, что он может находиться внутри ограниченной конструкции:

s/this/<<E . 'that'
the other
E
 . 'more '/eg;

Это работает так с версии Perl 5.18. Раньше это было несовместимым, и вам пришлось бы писать

s/this/<<E . 'that'
 . 'more '/eg;
the other
E

вне строковых вычислений.

Кроме того, правила цитирования для идентификатора конца строки не связаны с правилами цитирования Perl. q(), qq(), и т. п. не поддерживаются вместо '' и "", и единственная интерполяция — экранирование символа цитирования:

print << "abc\"def";
testing...
abc"def

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

Подробности парсинга цитируемых конструкций

Когда Perl сталкивается с чем-то, что может иметь несколько интерпретаций, он использует принцип DWIM (это «Do What I Mean») для выбора наиболее вероятной интерпретации. Эта стратегия настолько успешна, что программисты Perl часто не подозревают неоднозначность того, что они пишут. Но время от времени представления Perl существенно отличаются от того, что автор на самом деле хотел сказать.

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

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

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

Поиск конца

Первый проход — поиск конца цитируемой конструкции. Это приводит к сохранению в безопасном месте копии текста (между начальным и конечным разделителями), нормализованного по мере необходимости, чтобы не нужно было знать, какими были исходные разделители.

Если конструкция — here-документ, конечным разделителем является строка, содержащая строку завершения в качестве содержимого. Поэтому <<EOF завершается EOF непосредственно после "\n" и начинается с первого столбца строки завершения. При поиске строки завершения here-документа ничего не пропускается. Другими словами, строки после синтаксиса here-документа сравниваются со строкой завершения по строке.

Для конструкций, кроме here-документов, используются символы как начальные, так и конечные разделители. Если начальный разделитель — открывающая скобка (то есть (, [, {, или <), конечный разделитель — соответствующая закрывающая скобка (то есть ), ], }, или >). Если начальный разделитель — несбалансированный символ, например /, или закрывающая скобка, конечный разделитель такой же, как начальный разделитель. Таким образом, / завершает конструкцию qq//, а ] завершает как qq[], так и qq]] конструкции.

При поиске разделителей из одного символа пропускаются экранированные разделители и \\. Например, при поиске завершения /, пропускаются сочетания \\ и \/. Если разделители являются скобочными, также пропускаются вложенные пары. Например, при поиске закрывающей скобки ], соответствующей открывающей скобке [, пропускаются сочетания \\, \], и \[, а также вложенные [ и ]. Однако, когда обратные слэши используются в качестве разделителей (например, qq\\ и tr\\\), ничего не пропускается. Во время поиска конца обратные слэши, экранирующие разделители или другие обратные слэши, удаляются (точнее, они не копируются в безопасное место).

Для конструкций с разделителями из трёх частей (s///, y///, и tr///), поиск повторяется ещё раз. Если первый разделитель не является открывающей скобкой, все три разделителя должны быть одинаковыми, например, s!!! и tr))), в этом случае второй разделитель сразу завершает левую часть и начинает правую. Если левая часть ограничена скобочными разделителями (то есть (), [], {}, или <>), правой части нужны ещё пара разделителей, такие как s(){} и tr[]//. В этих случаях пробелы и комментарии допускаются между двумя частями, хотя комментарий должен следовать по крайней мере за одним пробелом; в противном случае символ, ожидаемый как начало комментария, может рассматриваться как начальный разделитель правой части.

При этом поиске не обращается внимания на семантику конструкции. Таким образом:

"$hash{"$foo/$bar"}"

или:

m/
  bar	# NOT a comment, this slash / terminated m//!
 /x

не образуют корректных выражений в кавычках. Цитируемая часть заканчивается на первом " и /, а остальное оказывается синтаксической ошибкой. Поскольку слэш, завершивший m//, следовал за SPACE, пример выше не является m//x, а скорее m// без модификатора /x. Таким образом, встроенный # интерпретируется как буквальный #.

Также во время этого поиска не обращается внимание на \c\ (синтаксис управляющего символа с несколькими символами). Таким образом, второй \ в qq/\c\/ интерпретируется как часть \/, а последующий / не распознаётся как разделитель. Вместо этого используйте \034 или \x1c в конце цитируемых конструкций.

Интерполяция

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

<<'EOF'

Интерполяция не выполняется. Обратите внимание, что комбинация \\ оставлена без изменений, так как экранированные разделители недоступны для here-доков.

m'', шаблон s'''

Интерполяция на этом этапе не выполняется. Любые последовательности с обратными слешами, включая \\, обрабатываются на этапе "Разбора регулярных выражений".

'', q//, tr''', y''', замена s'''

Единственная интерполяция — удаление \ из пар \\. Поэтому "-" в tr''' и y''' обрабатывается буквально как дефис, и диапазон символов недоступен. \1 в замене s''' не работает как $1.

tr///, y///

Интерполяция переменных не происходит. Комбинации для изменения строк в зависимости от регистра и кавычек, такие как \Q, \U, и \E, не распознаются. Другие последовательности с обратным слешем, такие как \200 и \t, и символы с обратным слешем, такие как \\ и \-, преобразуются в соответствующие литералы. Символ "-" обрабатывается специально, поэтому \- обрабатывается как литеральный символ "-".

"", ``, qq//, qx//, <file*glob>, <<"EOF"

\Q, \U, \u, \L, \l, \F (возможно, соединённые с \E) преобразуются в соответствующие конструкции Perl. Таким образом, "$foo\Qbaz$bar" преобразуется в $foo . (quotemeta("baz" . $bar)) во внутренней обработке. Другие последовательности с обратными слешами, такие как \200 и \t, и символы с обратными слешами, такие как \\ и \-, заменяются соответствующими расширениями.

Подчеркнём, что любое, что находится между \Q и \E, интерполируется обычным способом. Нечто вроде "\Q\\E" не имеет \E внутри. Вместо этого оно имеет \Q, \\, и E, поэтому результат такой же, как для "\\\\E". Как общее правило, обратные слеши между \Q и \E могут привести к неинтуитивным результатам. Таким образом, "\Q\t\E" преобразуется в quotemeta("\t"), что идентично "\\\t" (так как TAB не является буквенно-цифровым символом). Также обратите внимание, что:

$str = '\t';
return "\Q$str";

может быть ближе к предполагаемому намерению автора "\Q\t\E".

Интерполированные скаляры и массивы преобразуются во внутреннем представлении в операции конкатенации join и ".". Таким образом, "$foo XXX '@arr'" становится:

$foo . " XXX '" . (join $", @arr) . "'";

Все вышеперечисленные операции выполняются одновременно, слева направо.

Поскольку результат "\Q STRING \E" содержит все метасимволы в кавычках, нет способа вставить литеральный символ $ или @ внутри пары \Q\E. Если защищено \, $ будет помещено в кавычки и станет "\\\$"; в противном случае оно интерпретируется как начало интерполированного скаляра.

Также обратите внимание, что код интерполяции должен принять решение о том, где заканчивается интерполированный скаляр. Например, означает ли "a $x -> {c}":

"a " . $x . " -> {c}";

или:

"a " . $x -> {c};

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

Замена s///

Обработка \Q, \U, \u, \L, \l, \F и интерполяция происходит так же, как с конструкциями qq//.

Именно на этом шаге \1 неохотно преобразуется в $1 в тексте замены s///, чтобы исправить неустранимые ошибки хакеры sed, которые ещё не перешли к более разумному стилю. Выводится предупреждение, если псевдоним use warnings или командная строка -w (то есть, переменная $^W) были установлены.

RE в m?RE?, /RE/, m/RE/, s/RE/foo/,

Обработка \Q, \U, \u, \L, \l, \F, \E, и интерполяция происходит (почти) так же, как с конструкциями qq//.

Здесь также выполняется обработка \N{...}, и она компилируется в промежуточную форму для компилятора регулярных выражений. (Это связано с тем, что, как указано ниже, компиляция регулярных выражений может происходить во время выполнения, и \N{...} — это конструкция времени компиляции.)

Однако любые другие комбинации \, за которыми следует символ, не заменяются, а только пропускаются, чтобы обработать их как регулярные выражения на следующем шаге. Поскольку \c пропущен на этом шаге, @ из \c@ в RE, возможно, обрабатывается как символ массива (например, @foo), хотя тот же текст в qq// даёт интерполяцию \c@.

Блоки кода, такие как (?{BLOCK}), обрабатываются временно возвращением управления к парсеру Perl, аналогично тому, как интерполированное выражение индекса массива, такое как "foo$array[1+f("[xyz")]bar", было бы обработано.

Кроме того, внутри (?{BLOCK}), (?# comment ), и комментарий # в регулярном выражении /x, никакая обработка не выполняется. Это первый шаг, на котором присутствие модификатора /x имеет значение.

Интерполяция в шаблонах имеет несколько особенностей: $|, $(, $), @+ и @- не интерполируются, а конструкции $var[SOMETHING] голосуются (несколькими разными оценщиками) как элемент массива или $var, за которым следует альтернатива RE. Здесь становится полезной запись ${arr[$bar]}: /${arr[0-9]}/ интерпретируется как элемент массива -9, а не как регулярное выражение из переменной $arr, за которым следует цифра, что было бы интерпретацией /$arr[0-9]/. Поскольку голосование среди разных оценщиков может происходить, результат непредсказуем.

Отсутствие обработки \\ создаёт определённые ограничения на обработанный текст. Если разделитель /, то комбинацию \/ нельзя получить на этом шаге. / завершит регулярное выражение, \/ будет сокращён до / на предыдущем шаге, а \\/ останется неизменным. Поскольку / эквивалентно \/ внутри регулярного выражения, это не имеет значения, если разделитель является специальным символом для движка RE, как в s*foo*bar*, m[foo], или m?foo?; или буквенно-цифровым символом, как в:

m m ^ a \s* b mmx;

В приведённом выше регулярном выражении, намеренно замаскированном для иллюстрации, разделитель — m, модификатор — mx, а после удаления разделителя регулярное выражение такое же, как для m/ ^ a \s* b /mx. Есть не одна причина, почему вам рекомендуется ограничивать разделители небуквенно-цифровыми и непробельными символами.

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

Разбор регулярных выражений

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

Всё, что происходит в движке RE, возможно, лучше обсудить в perlre, но ради непрерывности, мы это сделаем здесь.

Это ещё один шаг, где присутствие модификатора /x имеет значение. Движок RE сканирует строку слева направо и преобразует её в конечный автомат.

Символы с обратными слешами либо заменяются соответствующими литеральными строками (как с \{), либо они генерируют специальные узлы в конечном автомате (как с \b). Символы, являющиеся специальными для движка RE (например, |), генерируют соответствующие узлы или группы узлов. (?#...) комментарии игнорируются. Всё остальное либо преобразуется в литеральные строки для сопоставления, либо игнорируется (как пробелы и комментарии в стиле #, если /x присутствует).

Разбор конструкции с квадратными скобками для определения класса символов, [...], отличается от правил, используемых для остальной части шаблона. Терминатор этой конструкции находится с использованием тех же правил, что и для нахождения терминатора {}-ограниченного конструкта, за исключением того, что ] сразу после [ обрабатывается так, как если бы ему предшествовал обратный слэш.

Терминатор для динамического (?{...}) находится путём временного переключения управления на парсер Perl, который должен остановиться в том месте, где находится логически сбалансированный завершающий }.

Возможно осмотреть как строку, переданную в движок RE, так и получившийся конечный автомат. Смотрите аргументы debug/debugcolor в псевдониме use re, а также командную строку Perl -Dr, описанную в "Командные переключатели" в perlrun.

Оптимизация регулярных выражений

Этот шаг указан только для полноты. Поскольку он не меняет семантику, подробности этого шага не документированы и могут быть изменены без предварительного уведомления. Этот шаг выполняется над конечным автоматом, сгенерированным на предыдущем этапе.

Именно на этом этапе split() молча оптимизирует /^/ до значения /^/m.

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

Вам следует ознакомиться с несколькими операторами ввода-вывода.

Строка, заключенная в обратные кавычки (гравированные акценты), сначала подвергается интерполяции двойных кавычек. Затем она интерпретируется как внешняя команда, и вывод этой команды является значением строки в обратных кавычках, как в оболочке. В скалярном контексте возвращается одна строка, содержащая весь вывод. В контексте списка возвращается список значений, по одному на каждую строку вывода. (Вы можете установить $/ для использования другого разделителя строк.) Команда выполняется каждый раз, когда псевдолитерал оценивается. Значение состояния команды возвращается в $? (см. perlvar для интерпретации $?). В отличие от csh, никакой перевод не выполняется на возвращаемых данных — новые строки остаются новыми строками. В отличие от любой из оболочек, одинарные кавычки не скрывают имена переменных в команде от интерпретации. Чтобы передать литеральную запятую в оболочку, вам нужно скрыть её с помощью обратного слэша. Обобщенная форма обратных кавычек — qx//, или вы можете вызвать функцию "readpipe" в perlfunc. (Поскольку обратные кавычки всегда подвергаются расширению оболочки, см. perlsec для проблем безопасности.)

В скалярном контексте, оценка дескриптора файла в угловых скобках возвращает следующую строку из этого файла (включая, при необходимости, символ новой строки), или undef в конце файла или при ошибке. Когда $/ установлено в значение undef (иногда известный как режим файла-слияния) и файл пустой, он возвращает '' первый раз, а затем undef в последующие разы.

Обычно вам необходимо присвоить возвращаемое значение переменной, но есть одна ситуация, когда происходит автоматическое присваивание. Если и только если входной символ является единственным элементом внутри условия оператора while (даже если он замаскирован как цикл for(;;)), значение автоматически присваивается глобальной переменной $_, уничтожая всё, что было там ранее. (Это может показаться странным, но вы будете использовать эту конструкцию практически в каждом скрипте Perl, который напишете.) Переменная $_ не неявно локальна. Вам необходимо поместить local $_; перед циклом, если вы хотите, чтобы это произошло. Кроме того, если входной символ или явное присваивание входного символа скаляру используется как условие while/for, то условие фактически проверяет определённость значения выражения, а не его обычное истинностное значение.

Таким образом, следующие строки эквивалентны:

while (defined($_ = <STDIN>)) { print; }
while ($_ = <STDIN>) { print; }
while (<STDIN>) { print; }
for (;<STDIN>;) { print; }
print while defined($_ = <STDIN>);
print while ($_ = <STDIN>);
print while <STDIN>;

Это также работает аналогично, но присваивает значение лексической переменной вместо $_:

while (my $line = <STDIN>) { print $line }

В этих циклических конструкциях присвоенное значение (автоматическое или явное присваивание) затем проверяется на определённость. Проверка на определённость предотвращает проблемы, когда строка имеет строковое значение, которое Perl интерпретирует как ложь; например, "" или "0" без заключительного символа новой строки. Если вы действительно хотите, чтобы такие значения завершали цикл, их следует явно проверить:

while (($_ = <STDIN>) ne '0') { ... }
while (<STDIN>) { last unless $_; ... }

В других контекстах с булевыми значениями <FILEHANDLE> без явной проверки defined или сравнения вызовет предупреждение, если use warnings псевдоним или опция командной строки -w (переменная $^W) активны.

Дескрипторы файлов STDIN, STDOUT и STDERR предопределены. (Дескрипторы файлов stdin, stdout, и stderr также будут работать, за исключением пакетов, где они будут интерпретироваться как локальные идентификаторы, а не глобальные.) Дополнительные дескрипторы файлов можно создать с помощью функции open(), среди прочих. См. perlopentut и "open" в perlfunc для получения подробной информации об этом.

Если используется дескриптор файла <FILEHANDLE> в контексте, ожидающем список, возвращается список, содержащий все строки ввода, по одной строке на элемент списка. Легко перейти к довольно большому объему данных таким способом, поэтому используйте с осторожностью.

<FILEHANDLE> также может быть написано как readline(*FILEHANDLE). См. "readline" в perlfunc.

Нулевой дескриптор файла <> (иногда называемый оператором алмаза) является специальным: он может быть использован для эмуляции поведения sed и awk, и любого другого программы Unix-фильтра, принимающего список имён файлов, выполняя ту же операцию над каждой строкой ввода из всех них. Ввод из <> происходит либо со стандартного ввода, либо из каждого файла, перечисленного в командной строке. Вот как это работает: в первый раз, когда оценивается <>, проверяется массив @ARGV, и если он пуст, $ARGV[0] устанавливается в "-", которое, при открытии, предоставляет стандартный ввод. Затем массив @ARGV обрабатывается как список имён файлов. Цикл

    while (<>) {
	...			# code for each line
    }

эквивалентен следующему псевдокоду, подобному Perl:

    unshift(@ARGV, '-') unless @ARGV;
    while ($ARGV = shift) {
	open(ARGV, $ARGV);
	while (<ARGV>) {
	    ...		# code for each line
	}
    }

за исключением того, что он не столь громоздкий для написания и фактически будет работать. Он действительно сдвигает массив @ARGV и помещает текущее имя файла в переменную $ARGV. Он также использует внутренний дескриптор файла ARGV. <> просто синоним <ARGV>, который является магическим. (Псевдокод выше не работает, потому что он рассматривает <ARGV> как не-магический.)

Поскольку нулевой дескриптор файла использует двухаргументную форму "open" в perlfunc, он интерпретирует специальные символы, поэтому если у вас есть скрипт такого вида:

while (<>) {
    print;
}

и вы вызываете его с perl dangerous.pl 'rm -rfv *|', он фактически открывает канал, выполняет команду rm и считывает вывод rm из этого канала. Если вы хотите, чтобы все элементы в @ARGV интерпретировались как имена файлов, вы можете использовать модуль ARGV::readonly с CPAN или использовать двойные угловые скобки:

while (<<>>) {
    print;
}

Использование двойных угловых скобок внутри цикла while приводит к тому, что open использует трехаргументную форму (со вторым аргументом <), поэтому все аргументы в ARGV обрабатываются как имена файлов (включая "-"). (Обратите внимание, что для удобства, если вы используете <<>> и если @ARGV пусто, он все равно будет читать со стандартного ввода.)

Вы можете изменить @ARGV перед первым <>, пока массив в итоге содержит список имен файлов, которые вам действительно нужны. Номера строк ($.) продолжаются, как будто вход был одним большим счастливым файлом. Обратитесь к примеру в "eof" в perlfunc для того, как сбросить номера строк для каждого файла.

Если вы хотите установить @ARGV в свой собственный список файлов, делайте это. Это устанавливает @ARGV во все текстовые файлы, если @ARGV не указан:

@ARGV = grep { -f && -T } glob('*') unless @ARGV;

Вы даже можете установить их в команды канала. Например, это автоматически фильтрует сжатые аргументы через gzip:

@ARGV = map { /\.(gz|Z)$/ ? "gzip -dc < $_ |" : $_ } @ARGV;

Если вы хотите передавать параметры в свой скрипт, вы можете использовать один из модулей Getopts или поместить цикл в начало, как в этом примере:

    while ($_ = $ARGV[0], /^-/) {
	shift;
        last if /^--$/;
	if (/^-D(.*)/) { $debug = $1 }
	if (/^-v/)     { $verbose++  }
	# ...		# other switches
    }

    while (<>) {
	# ...		# code for each line
    }

Символ <> вернет undef только один раз при достижении конца файла. Если вы вызовете его снова после этого, он предположит, что вы обрабатываете другой @ARGV список, и если вы не установили @ARGV, будет читать вход с STDIN.

Если в угловых скобках содержится простая скалярная переменная (например, $foo), эта переменная содержит имя дескриптора файла для ввода, его типглоб или ссылку на него. Например:

$fh = \*STDIN;
$line = <$fh>;

Если то, что находится в угловых скобках, не является дескриптором файла и не является простой скалярной переменной, содержащей имя дескриптора файла, типглоб или ссылку на типглоб, то это интерпретируется как шаблон имени файла для подстановки, и возвращается либо список имён файлов, либо следующее имя файла в списке, в зависимости от контекста. Это различие определяется только синтаксически. Это означает, что <$x> всегда является readline() от косвенного дескриптора, но <$hash{key}> всегда является glob(). Это потому, что $x является простой скалярной переменной, но $hash{key} — нет, это элемент хэша. Даже <$x > (обратите внимание на дополнительный пробел) обрабатывается как glob("$x "), а не readline($x).

Сначала выполняется один уровень интерпретации двойных кавычек, но вы не можете сказать <$foo>, потому что это косвенный дескриптор файла, как объяснялось в предыдущем абзаце. (В старых версиях Perl программисты вставляли фигурные скобки, чтобы принудительно интерпретировать это как шаблон имени файла: <${foo}>. В наши дни считается более чистым вызывать внутреннюю функцию напрямую, как glob($foo), что, вероятно, и было правильным способом сделать это с самого начала.) Например:

    while (<*.c>) {
	chmod 0644, $_;
    }

приблизительно эквивалентно:

    open(FOO, "echo *.c | tr -s ' \t\r\f' '\\012\\012\\012\\012'|");
    while (<FOO>) {
	chomp;
	chmod 0644, $_;
    }

за исключением того, что подстановка выполняется внутри с помощью стандартного расширения File::Glob. Конечно, самый короткий способ сделать вышеперечисленное — это:

chmod 0644, <*.c>;

Шаблон имени файла (глоб) оценивает свой (встроенный) аргумент только при запуске нового списка. Все значения должны быть прочитаны перед тем, как он начнётся заново. В контексте списка это не важно, потому что вы автоматически получаете их все. Однако в скалярном контексте оператор возвращает следующее значение каждый раз, когда он вызывается, или undef, когда список исчерпан. Как и при чтении с дескриптора файла, автоматическая defined генерируется, когда шаблон имени файла (глоб) встречается в части проверки оператора while, потому что законный результат подстановки (например, файл с именем 0) в противном случае приведёт к завершению цикла. Опять же, undef возвращается только один раз. Поэтому, если вы ожидаете единственное значение из подстановки, намного лучше сказать

($file) = <blurch*>;

чем

$file = <blurch*>;

потому что последнее будет попеременно возвращать имя файла и возвращать ложь.

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

@files = glob("$dir/*.[ch]");
@files = glob($files[$i]);

Если выражение подстановки, использующее угловые скобки, используется как условие цикла while или for, оно неявно присваивается $_. Если либо выражение подстановки, либо явное присваивание выражения подстановки скаляру используется как условие while/for, то условие фактически проверяет определённость значения выражения, а не его обычное истинностное значение.

Постоянное складывание

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

  'Now is the time for all'
. "\n"
.  'good men to come to.'

и всё это сводится к одной строке во внутренней реализации. Аналогично, если вы скажете

    foreach $file (@filenames) {
	if (-s $file > 5 + 100 * 2**16) {  }
    }

компилятор предварительно вычисляет число, которое представляет это выражение, чтобы интерпретатор не должен был этого делать.

Операторы no-op

В Perl официально нет оператора no-op, но голые константы 0 и 1 являются специальными случаями, не генерирующими предупреждение в контексте void, поэтому вы можете, например, безопасно сделать

1 while foo();

Битовые операторы для строк

Битовые строки любого размера можно обрабатывать с помощью битовых операторов (~ | & ^).

Если операнды битового оператора — это строки разной длины, операторы | и ^ ведут себя так, как будто у более короткого операнда справа были добавлены дополнительные нули, а оператор & — как будто более длинный операнд был усечён до длины более короткого. Граница для такого расширения или усечения — один или несколько байтов.

# ASCII-based examples
print "j p \n" ^ " a h";        	# prints "JAPH\n"
print "JA" | "  ph\n";          	# prints "japh\n"
print "japh\nJunk" & '_____';   	# prints "JAPH\n";
print 'p N$' ^ " E<H\n";		# prints "Perl\n";

Если вы намерены обрабатывать битовые строки, убедитесь, что вы предоставляете битовые строки: если операнд — это число, это подразумевает арифметическую битовую операцию. Вы можете явно указать, какой тип операции вы имеете в виду, используя "" или 0+, как в примерах ниже.

$foo =  150  |  105;	# yields 255  (0x96 | 0x69 is 0xFF)
$foo = '150' |  105;	# yields 255
$foo =  150  | '105';	# yields 255
$foo = '150' | '105';	# yields string '155' (under ASCII)

$baz = 0+$foo & 0+$bar;	# both ops explicitly numeric
$biz = "$foo" ^ "$bar";	# both ops explicitly stringy

Это несколько непредсказуемое поведение можно избежать с помощью функции «bitwise», новой в Perl 5.22. Вы можете включить её через use feature 'bitwise' или use v5.28. Перед Perl 5.28 она генерировала предупреждение в категории "experimental::bitwise". В рамках этой функции четыре стандартных битовых оператора (~ | & ^) всегда являются арифметическими. Добавление точки после каждого оператора (~. |. &. ^.) заставляет его рассматривать операнды как строки:

use feature "bitwise";
$foo =  150  |  105;	# yields 255  (0x96 | 0x69 is 0xFF)
$foo = '150' |  105;	# yields 255
$foo =  150  | '105';	# yields 255
$foo = '150' | '105';	# yields 255
$foo =  150  |. 105;	# yields string '155'
$foo = '150' |. 105;	# yields string '155'
$foo =  150  |.'105';	# yields string '155'
$foo = '150' |.'105';	# yields string '155'

$baz = $foo &  $bar;	# both operands numeric
$biz = $foo ^. $bar;	# both operands stringy

Операторы присваивания с этими операторами (&= |= ^= &.= |.= ^.=) ведут себя аналогично в рамках этой функции.

Ошибка fatal возникает, если операнд содержит символ, значение ординала которого выше 0xFF и, следовательно, не может быть выражено иначе, чем в UTF-8. Операция выполняется на копии без UTF-8 для других операндов, закодированных в UTF-8. Смотрите "Семантика байтов и символов" в perlunicode.

Для получения информации о том, как обрабатывать отдельные биты в битовом векторе, обратитесь к "vec" в perlfunc.

Целочисленная арифметика

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

use integer;

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

no integer;

что действует до конца этого BLOCK. Обратите внимание, что это не означает, что всё становится целым числом, а лишь то, что Perl будет использовать целочисленные операции для арифметических, сравнительных и битовых операторов. Например, даже при use integer, если вы возьмёте sqrt(2), вы всё равно получите 1.4142135623731 или около того.

При использовании с числами битовые операторы (& | ^ ~ << >>) всегда производят целочисленные результаты. (Но см. также "Битовые операторы для строк".) Однако use integer всё ещё имеет для них смысл. По умолчанию их результаты интерпретируются как беззнаковые целые числа, но если use integer активен, их результаты интерпретируются как знаковые целые числа. Например, ~0 обычно вычисляется в большое целочисленное значение. Однако use integer; ~0 составляет -1 на машинах с дополнением до двух.

Арифметика с плавающей точкой

В то время как use integer предоставляет только целочисленную арифметику, нет аналогичного механизма для автоматического округления или усечения до определённого числа десятичных знаков. Для округления до определённого числа знаков обычно проще использовать sprintf() или printf(). Смотрите perlfaq4.

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

printf "%.20g\n", 123456789123456789;
#        produces 123456789123456784

Проверка на точное равенство или неравенство чисел с плавающей точкой — не лучшая идея. Вот обходной путь (относительно дорогой), чтобы сравнить, равны ли два числа с плавающей точкой конкретному числу с определённым количеством десятичных знаков. Более надёжное решение этой проблемы можно найти в книге Кнута, том II.

    sub fp_equal {
	my ($X, $Y, $POINTS) = @_;
	my ($tX, $tY);
	$tX = sprintf("%.${POINTS}g", $X);
	$tY = sprintf("%.${POINTS}g", $Y);
	return $tX eq $tY;
    }

Модуль POSIX (входит в стандартное распределение Perl) реализует ceil(), floor(), и другие математические и тригонометрические функции. Модуль Math::Complex (входит в стандартное распределение Perl) определяет математические функции, которые работают как с вещественными, так и с комплексными числами. Math::Complex не так эффективен, как POSIX, но POSIX не может работать с комплексными числами.

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

Большие числа

Стандартные Math::BigInt, Math::BigRat, и Math::BigFloat модули, наряду с bignum, bigint, и bigrat пragmaми, предоставляют арифметику с переменной точностью и перегруженные операторы, хотя они сейчас довольно медленные. В обмен на некоторый объём памяти и значительную потерю скорости они избегают обычных проблем, связанных с ограниченной точностью представления.

	use 5.010;
	use bigint;  # easy interface to Math::BigInt
	$x = 123456789123456789;
	say $x * $x;
    +15241578780673678515622620750190521

Или с рациональными числами:

use 5.010;
use bigrat;
$x = 3/22;
$y = 4/6;
say "x/y is ", $x/$y;
say "x*y is ", $x*$y;
x/y is 9/44
x*y is 1/11

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

Вот краткий, но неполный обзор:

Math::String           treat string sequences like numbers
Math::FixedPrecision   calculate with a fixed precision
Math::Currency         for currency calculations
Bit::Vector            manipulate bit vectors fast (uses C)
Math::BigIntFast       Bit::Vector wrapper for big numbers
Math::Pari             provides access to the Pari C library
Math::Cephes           uses the external Cephes C library (no
                       big numbers)
Math::Cephes::Fraction fractions via the Cephes library
Math::GMP              another one using an external C library
Math::GMPz             an alternative interface to libgmp's big ints
Math::GMPq             an interface to libgmp's fraction numbers
Math::GMPf             an interface to libgmp's floating point numbers

Выбирайте с умом.

© 1993–2023 Larry Wall and others
Licensed under the GNU General Public License version 1 or later, or the Artistic License.
The Perl logo is a trademark of the Perl Foundation.
https://perldoc.perl.org/5.38.0/perlop

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API