Как я могу запретить Perl интерпретировать двойную обратную косую черту как символ одинарной обратной косой черты?

Как я могу напечатать строку (в одинарных кавычках), содержащую двойную обратную косую черту \\ символы как есть, не заставляя Perl каким-то образом интерполировать его в один слэш \? Я не хочу изменять строку, добавляя также дополнительные escape-символы.

my $string1 = 'a\\\b';
print $string1; #prints 'a\b'

my $string1 = 'a\\\\b';
    #I know I can alter the string to escape each backslash
    #but I want to keep string as is.
print $string1; #prints 'a\\b'

#I can also use single-quoted here document
#but unfortunately this would make my code syntactically look horrible.
my $string1 = <<'EOF';
a\\b
EOF
print $string1; #prints a\\b, with newline that could be removed with chomp

3 ответа

Единственная цитатная конструкция в Perl, которая вообще не интерпретирует обратную косую черту, - это документ, заключенный в одинарные кавычки:

my $string1 = <<'EOF';
a\\\b
EOF
print $string1; # Prints a\\\b, with newline

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

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

Если вы слегка сумасшедший и вам нравится идея использовать экспериментальное программное обеспечение, использующее внутренние компоненты Perl для улучшения эстетики вашего кода, вы можете использовать модуль https://metacpan.org/pod/Syntax::Keyword::RawQuote в CPAN с сегодняшнего утра.

use syntax 'raw_quote';
my $string1 = r'a\\\b';
print $string1; # prints 'a\\\b'

Спасибо @melpomene за вдохновение.

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

my $string = 'a!!!b';
$string =~ s{!}{\\}g;
print $string; #prints 'a\\\b'

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

sub bs {
    $_[0] =~ s{!}{\\}gr
}

my $string = 'a!!!b';
print bs($string); #prints 'a\\\b'

PS Эта функция использует модификатор неразрушающего замещения /r введено в v5.14, Если вы используете более старую версию, тогда функцию нужно написать так

sub bs {
    $_[0] =~ s{!}{\\}g;
    return $_[0];
}

Или если вам нравится что-то более читабельное

sub bs {
    my $str = shift;
    $str =~ s{!}{\\}g;
    return $str;
}
Другие вопросы по тегам