Строки в Perl: кавычки, интерполяция и экранирование
Понимание того, как работают строки, важно при изучении любого языка программирования, но в 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
Published on 2013-09-06