Почему q / \\ a / равно q / \ a /?

В следующем примере печатается «ЖЕ»:

if (q/\\a/ eq q/\a/) {
    print "SAME\n";
}
else {
    print "DIFFERENT\n";
}

Я понимаю, что это соответствует документации. Но я считаю такое поведение нежелательным. Есть ли необходимость избегать lilteral люфта в строке, заключенной в одинарные кавычки? Если бы я хотел 2 люфта, мне нужно было бы указать 4; это не кажется удобным.

Разве Perl не должен определять, служит ли обратная косая черта escape-символом или нет? Например, если обратная косая черта не предшествует разделителю, ее следует рассматривать как литерал; и если бы это было так, мне бы не понадобилось 3 обратных косых черты для выражения двух, например,

q<a\\b>

вместо того

q<a\\\b>.

person Ltf4an    schedule 12.12.2016    source источник
comment
Попробуйте использовать q/\/, и вы увидите, что нужно избегать обратной косой черты.   -  person cHao    schedule 12.12.2016
comment
Извините, я не совсем понял свой первоначальный вопрос. Я добавил слово «литерал», чтобы подчеркнуть тот факт, что обратная косая черта не работает как escape-символ. Ваш пример не отражает мою точку зрения, так как в вашем случае, согласно определению, обратная косая черта, предшествующая разделителю, действует как escape-символ.   -  person Ltf4an    schedule 13.12.2016
comment
когда обратная косая черта не предшествует разделителю, ее следует рассматривать как литерал. Как же тогда создать строку, которая заканчивается обратной косой чертой? q/\/ - ›косая черта, без закрывающего разделителя (синтаксическая ошибка); q/\\/ - ›буквальная обратная косая черта, буквальная косая черта, без закрывающего разделителя (синтаксическая ошибка); q/\\\/ - ›буквальная обратная косая черта, буквальная обратная косая черта, буквальная косая черта, без закрывающего разделителя (синтаксическая ошибка); ...   -  person ThisSuitIsBlackNot    schedule 13.12.2016
comment
... как создать строку, оканчивающуюся обратной косой чертой? --- Отличный вариант использования! Поскольку он действительно предшествует (закрывающему) разделителю, его не следует рассматривать как литерал, и поэтому его нужно экранировать. Помимо этого варианта использования, я думаю, что мое предложение сработает, когда люфт появляется где-то внутри, а не рядом с закрывающим разделителем.   -  person Ltf4an    schedule 13.12.2016
comment
@ Ltf4an Да, но как узнать, что вы достигли закрывающего разделителя? q/\\/ может быть одиночной (экранированной) обратной косой чертой или может быть просто началом строки \/, с последующими вправо. Какой выбирает парсер? То, что вы описали, неоднозначно.   -  person ThisSuitIsBlackNot    schedule 13.12.2016
comment
@ThisSuitIsBlackNot, как насчет того, чтобы вернуться назад от закрывающего разделителя? Я бы подумал, что 1-й символ, предшествующий закрывающему разделителю, не должен быть люфтом. Если да, то это ошибка; если это не так, но это еще один закрывающий разделитель, тогда следующий предшествующий символ должен быть люфтом и т. д.   -  person Ltf4an    schedule 14.12.2016
comment
Вы не можете идти назад от закрывающего ограничителя, если не знаете, где находится закрывающий ограничитель.   -  person ThisSuitIsBlackNot    schedule 14.12.2016


Ответы (2)


Есть ли необходимость избегать люфта в строке, заключенной в одинарные кавычки?

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

$ perl -e'print q/C:\/'
Can't find string terminator "/" anywhere before EOF at -e line 1.
$ perl -e'print q/C:\\/'
C:\

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


Если бы я хотел 2 люфта, мне нужно было бы указать 4; это не кажется удобным.

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

my $path = <<'END';
C:\a\very\long\path
END

chomp $path;
print $path; # C:\a\very\long\path

Обратите внимание, что heredoc добавляет в конец новую строку, которую вы можете удалить с помощью chomp.

person ThisSuitIsBlackNot    schedule 12.12.2016
comment
вы можете использовать heredoc в одинарных кавычках, который не требует экранирования Спасибо за это. Я всегда считал, что heredoc с ограничителем в одинарных кавычках ведет себя точно так же, как и строка в одинарных кавычках, за исключением того, что здесь нет разделителя, который нужно экранировать, поэтому нужно избегать только нескольких обратных косых черт. Мне очень приятно ошибаться. - person Borodin; 12.12.2016
comment
Я отредактировал свой вопрос, чтобы указать, что Perl должен различать буквальную обратную косую черту и экранирование обратной косой черты. - person Ltf4an; 13.12.2016

В строковых литералах в одинарных кавычках

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

Другими словами,

  • Вы должны избегать разделителей.
  • Вы должны экранировать \, за которым следует \ или разделитель.
  • Вы можете экранировать \, за которым не следует \ или разделитель.

So,

q/\//      ⇒   /
q/\\\\a/   ⇒   \\a
q/\\\a/    ⇒   \\a
q/\\a/     ⇒   \a
q/\a/      ⇒   \a

Есть ли необходимость избегать люфта в строке, заключенной в одинарные кавычки?

Да, если за ним следует обратная косая черта или разделитель.

Если бы я хотел 2 люфта, мне нужно было бы указать 4

Трех было бы достаточно.

это не кажется удобным.

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

person ikegami    schedule 12.12.2016