Понимание того, как работают строки, важно при изучении любого языка программирования, но в 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