Строки в Perl: кавычки, интерполяция и экранирование

strings escape character interpolation quote embedded characters q qq

Понимание того, как работают строки, важно при изучении любого языка программирования, но в Perl они часть самой сути языка. Особенно если вспомнить, что одна из расшифровок названия языка звучит как Practical Extraction and Reporting Language (Практический язык извлечения данных и составления отчетов), а для этого нужно много работать со строками.

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

Строки в одинарных кавычках

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

my $name = 'Foo';
print 'Привет $name, как дела?\n';

Этот код выведет:

Привет $name, как дела?\n

Строки в двойных кавычках

Строки, заключенные в двойные кавычки " обеспечивают интерполяцию (переменные, включенные в строку заменяются на их содержимое), а также в них заменяются специальные escape-последовательности, например \n заменяется на перевод строки, а \t - на табуляцию.

my $name = 'Foo';
my $time  = "сегодня";
print "Привет $name,\nкак у тебя дела $time?\n";

Вывод:

Привет Foo,
как у тебя дела сегодня?

Обратите внимание на \n после запятой в строке и еще один в конце строки.

Для простых строк, таких как 'Foo' и "сегодня", в которых не встречаются символы $, @, и \, неважно, в какие кавычки они заключены.

Следующие две строки работают одинаково:

$name = 'Foo';
$name = "Foo";

Адреса E-mail

Поскольку @ тоже интерполируется в строках с двойными кавычками, стоит обратить внимание на написание адресов e-mail.

В строках с одинарными кавычками @ не интерполируется.

В случае с двойными кавычками такой код

use strict;
use warnings;
my $broken_email  = "foo@bar.com";

выдаст ошибку: Global symbol "@bar" requires explicit package name at ... line ... и предупреждение: Possible unintended interpolation of @bar in string at ... line ...

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

С другой стороны, этот код с адресом e-mail в одиночных кавычках, будет работать.

use strict;
use warnings;
my $good_email  = 'foo@bar.com';

Но что если вам и нужна интерполяция скалярных переменных, и в строке должен быть знак @?

use strict;
use warnings;
my $name = 'foo';
my $good_email  = "$name\@bar.com";

print $good_email; # foo@bar.com

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

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

Похожим образом, если вы хотите включить в строку с двойными кавычками знак $, вы можете его тоже экранировать:

use strict;
use warnings;
my $name = 'foo';
print "\$name = $name\n";

Вывод:

$name = foo

Экранирование экранирующего символа

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

Впрочем, не беспокойтесь. Можно указать Perl'у, что нам это не надо, экранировав экранирующий символ:

Просто нужно добавить еще один обратный слеш:

use strict;
use warnings;
my $name = 'foo';
print "\\$name\n";
\foo

Я знаю, что экранирование экранирующего символа это немного странно, но, в общем-то, так это работает в любом языке программирования.

Если вы хотите досконально разобраться в экранировании, попробуйте что-нибудь такое:

print "\\\\n\n\\n\n";

посмотрите, на вывод:

\\n
\n

и попробуйте разобраться с этим самостоятельно.

Экранирование двойных кавычек

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

Мы узнали, как использовать экранирующий символ \ и как экранировать его самое.

А что, если нам нужно вывести двойную кавычку в строке с двойными кавычками?

В этом коде содержится синтаксическая ошибка:

use strict;
use warnings;
my $name = 'foo';
print "The "name" is "$name"\n";

когда Perl видит двойную кавычку перед словом "name", он думает, что строка закончилась, и жалуется на то, что слово name - bareword.

Как вы могли догадаться, нужно экранировать символ " в строке:

use strict;
use warnings;
my $name = 'foo';
print "The \"name\" is \"$name\"\n";

Вывод:

The "name" is "foo"

Это работает, хотя немного сложно читаемо.

qq, оператор double-q

Здесь уместно использовать qq, или оператор double-q:

use strict;
use warnings;
my $name = 'foo';
print qq(The "name" is "$name"\n);

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

Мы заменили двойные кавычки " вокруг строки на скобки оператора qq. Это значит, что двойные кавычки больше не имеют специального значения в этой строке, так что нам больше не нужно экранировать их. Таким образом, код становится куда читаемее. Я бы сказал, что это прекрасно, если бы не боялся гнева Python-программистов.

Но что если вы хотите включить в строку скобки?

use strict;
use warnings;
my $name = 'foo';
print qq(The (name) is "$name"\n);

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

Я знаю. Теперь вы хотите все сломать, поставив закрывающую скобку перед открывающей:

use strict;
use warnings;
my $name = 'foo';
print qq(The )name( is "$name"\n);

Действительно, perl выдаст вас синтаксическую ошибку, указывающую на "name" как на bareword. Ведь он не может понять все, верно?

Конечно, вы можете экранировать скобки в строке с помощью \) и \(, но в эту ловушку мы уже попадали. Нет, спасибо!

Должен быть способ получше!

Помните, выше я говорил, что qq - это оператор, а не функция. Так что в нем есть свои хитрости, верно?

Что если заменить круглые скобки фигурными? {}:

use strict;
use warnings;
my $name = 'foo';
print qq{The )name( is "$name"\n};

Это сработает и выведет строку так, как мы и хотели:

The )name( is "foo"

(хотя я не могу представить, зачем бы мне понадобилось выводить что-нибудь вроде этого...)

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

Что-то вроде этого, верно?

use strict;
use warnings;
my $name = 'foo';
print qq[The )name} is "$name"\n];

вывод:

The )name} is "foo"

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

q, оператор single-q

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

use strict;
use warnings;
print q[The )name} is "$name"\n];

вывод:

The )name} is "$name"\n

Otras páginas

Учебник Perl по-русски

Author

Gabor Szabo (szabgab) Gabor Szabo