Perl: правильное цитирование всех специальных символов

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

my $string = "use Ppppp\\Ppppp;";
print $string;

Оба, двойные кавычки или кавычки будут напечатаны

use Ppppp\Ppppp;

С использованием

my $string = "\Quse Ppppp\\Ppppp;\E";
print $string;

будет печатать

use\ Ppppp\\Ppppp\;

добавление этих дополнительных обратных косых черт к выходным данным.

Есть ли в Perl простое решение для отображения строки «буквально», без изменения строки, например добавления дополнительных обратных косых черт для выхода?


person Claude    schedule 22.01.2019    source источник
comment
Вы хотите экранировать только специальные символы, а не пробелы?   -  person Corion    schedule 22.01.2019
comment
\Q\E, который внутренне представляет собой просто интерполированную форму функции quotemeta, экранирует все символы ASCII, кроме [A-Za-z_0-9], как задокументировано . В частности, это означает, что пробелы будут экранированы. Что именно вы хотите избежать?   -  person Grinnz    schedule 22.01.2019
comment
Я хочу, чтобы строка (например, уже предоставленный пример) печаталась точно со всеми обратными косыми чертами или другими специальными символами. Я не понимаю, почему \Q\E добавляет эти дополнительные обратные косые черты, пытаясь избежать пробела и ;   -  person Claude    schedule 22.01.2019
comment
Потому что это его цель - избежать всего, кроме класса, указанного @Grinnz. Поскольку вы не хотите экранировать все, вам нужно будет указать точный список либо того, что вы хотите экранировать (и экранировать явно), либо того, что вы не делаете. нужно экранировать, чтобы вы могли их сохранить (см. мой ответ).   -  person zdim    schedule 22.01.2019
comment
кавычка разработана как общий механизм экранирования. Он не может знать, какие символы будут специальными для того, для чего вы его используете - пробелы и точки с запятой являются специальными в определенных контекстах (оболочки, SQL - хотя есть лучшие варианты, чем кавычки для любого из них). Поэтому я спросил, что точно вы хотите избежать.   -  person Grinnz    schedule 22.01.2019
comment
здим, ты внимательно проверил мой вопрос? Ну у меня эта строка use Proxy\\Proxy; Подскажите как именно отображать, включая обратную косую черту.   -  person Claude    schedule 22.01.2019
comment
Клод: Нет, эта строка есть в исходном коде. Perl всегда анализирует обратную косую черту в строках, так что две обратные косые черты представляют собой одну обратную косую черту в значении. Если вам нужны две обратные косые черты, вам нужно написать четыре обратных косых черты в исходном коде.   -  person Corion    schedule 22.01.2019
comment
кавычки не подходят для этой работы, вам нужно правильно сконструировать их, например, как my $str = 'use Proxy\\\\Proxy;'; — вам нужно экранировать обратную косую черту, чтобы включить их в строковые литералы в Perl, за исключением здесь-документы в одинарных кавычках или в строках в одинарных кавычках, если за ними не следует одинарная кавычка или другая обратная косая черта.   -  person Grinnz    schedule 22.01.2019
comment
@Claude Клод Да, я внимательно рассмотрел твой вопрос. Проблема в том, что он показывает только одну строку примера; что еще может быть у вас? Вы внимательно видели мой ответ и комментарий выше? Чтобы правильно обработать не только один пример, вам нужно знать, что точно вы хотите оставить без изменений. Если вы просто хотите, чтобы строка была напечатана буквально как есть, тогда это немного отличается. Это то, что вам нужно?   -  person zdim    schedule 22.01.2019
comment
Строки приходят такими, какие они есть, я не хочу изменять строки, добавляя дополнительные escape-последовательности с помощью \. Я только хочу, чтобы они были напечатаны точно, мне нужен способ автоматически экранировать все в строке без редактирования строки. Просто подумайте о тысячах специальных строк со всевозможными специальными символами.   -  person Claude    schedule 22.01.2019
comment
Если вы напишите это в своем исходном коде таким образом, это не совсем так, потому что вы создали строку только с одной обратной косой чертой. Если он поступает из внешнего ввода, такого как дескриптор файла, или вы помещаете его в одинарные кавычки здесь-документа, как указано в комментарии выше, тогда он будет точно таким, каким он появляется.   -  person Grinnz    schedule 22.01.2019
comment
Хорошо понял. Дело запуталось из-за того, что вы использовали слово escape - очевидно, вы не хотите экранировать вещи, а просто хотите, чтобы строка была напечатана буквально. Проблема там как раз в самом двойном обратном слэше   -  person zdim    schedule 22.01.2019
comment
Да, здим. Мне нужен способ только печатать строку буквально. Это всего лишь образец строки, мне нужно обработать тысячи. \Q\E должен выполнить эту работу, но вставьте эти дополнительные \, а я этого не хочу.   -  person Claude    schedule 22.01.2019
comment
@Claude Клод Нет, \Q\E не будет делать то, что ты хочешь; их работа состоит в том, чтобы избежать чего-то, что обычно означает добавление обратной косой черты.   -  person zdim    schedule 22.01.2019
comment
quotemeta не подходит для этой задачи, потому что к моменту ее запуска нужные вам обратные косые черты уже исчезли. Все ваши строки написаны непосредственно в исходном коде, как в вашем примере, или они берутся откуда-то еще?   -  person Grinnz    schedule 22.01.2019
comment
@Claude Основная цель \Q\E - избежать любых символов, которые могут быть особенными для регулярных выражений. Кажется, вам нужна какая-то другая схема экранирования, поэтому вам нужно сказать, для чего, и дать полный список того, что вы считаете всеми специальными символами, включая обратную косую черту. Может быть, вы ищете что-то вроде pp из Data::Dump? Кроме того, важно отметить, что строка Perl "use Proxy\\Proxy;" содержит только одну обратную косую черту.   -  person haukex    schedule 22.01.2019
comment
@Claude Подводя итог: вы хотите, чтобы ваши строки печатались буквально (так что не экранированы или заключены в кавычки), что легко, за исключением комбинации с двойной обратной косой чертой, как указано несколькими людьми выше. Итак, ключевой вопрос: как данные — эти строки — попадают в вашу программу?   -  person zdim    schedule 22.01.2019
comment
Есть хэш, с которым я должен сопоставляться, но я не хотел усложнять вопрос. В моем примере хеш-ключ использует Proxy\\Proxy;. Если я сравниваю строку, полученную из внешнего текста, она не будет совпадать, потому что в этом примере строка интерпретируется как use Proxy\Proxy;. Вот почему мне нужен способ, чтобы строка оставалась точно такой же.   -  person Claude    schedule 22.01.2019
comment
@Claude Еще раз: пожалуйста, как данные попадают в вашу программу? Из файла?   -  person zdim    schedule 22.01.2019
comment
Да, проблема с этой двойной комбинацией обратной косой черты.   -  person Claude    schedule 22.01.2019
comment
zdim, я не думаю, что это имеет какое-то значение. Я хочу распечатать \use Proxy\\Proxy; без добавления дополнительных обратных слэшей к строке. Это все.   -  person Claude    schedule 22.01.2019
comment
@Claude Как выглядит хэш-ключ, когда вы выгружаете хэш с помощью такого модуля, как Data::Dump? Если он показывает "use Proxy\\Proxy;", опять же, эта строка содержит только один символ обратной косой черты. Если он показывает "use Proxy\\\\Proxy;", то строка действительно содержит два символа обратной косой черты. Вам нужно сделать ту же проверку строки, которую вы ищете.   -  person haukex    schedule 22.01.2019
comment
@Claude Re Я не думаю, что это имеет какое-то значение -- ладно, удачи   -  person zdim    schedule 22.01.2019
comment
Какое значение это может иметь? С уважением.... Допустим, у меня есть эта строка use Proxy\\Proxy; из какого-то источника, и я хочу напечатать его именно так, как есть. В любом случае спасибо за ваш совет. Я нашел это stackoverflow.com/questions/42331653/ Я не думал, что для этого нет простого решения.   -  person Claude    schedule 22.01.2019
comment
Важно то, что если вы напишете "use Proxy\\Proxy;" буквально в своей программе, вы создадите строку use Proxy\Proxy;, потому что синтаксический анализатор Perl таким образом обрабатывает обратную косую черту в строковых литералах в кавычках, так что это то, что будет содержать ваша строка; но если вы прочитаете из файла текст use Proxy\\Proxy; в строку, у вас будет именно этот текст.   -  person Grinnz    schedule 22.01.2019
comment
Я не знаю, я думал, что мой пример был очень ясным. У меня есть строка, неважно, откуда она берется, и я хочу напечатать ее точно, не изменяя строку. Похоже, что в Perl нет простого решения, я ошибаюсь?   -  person Claude    schedule 22.01.2019
comment
@Claude Важно то, что люди, пытающиеся помочь вам, просят дополнительную информацию, чтобы помочь вам решить вашу проблему. Я предлагаю вам потратить время, чтобы снова прочитать все комментарии и предоставить информацию, запрошенную при редактировании вашего вопроса. Также взгляните на MCVE. Кстати, способ распечатать его точно так, как он есть, это print. Как и Гриннз, я думаю, что путаница здесь, и то, что все пытаются сказать, может быть в том, что когда вы пишете "use Proxy\\Proxy;" в исходном коде Perl, эта строка имеет только одну обратную косую черту.   -  person haukex    schedule 22.01.2019
comment
Откуда он исходит, определяет, как решить вашу проблему, поэтому это важно.   -  person Grinnz    schedule 22.01.2019
comment
@ Клод Ты ошибаешься. Способ печати строки как есть — print.   -  person melpomene    schedule 22.01.2019
comment
У меня есть образец строки, содержащий 2 обратных слэша. Нет, у вас их нет. Как объяснялось в комментариях выше, у вас есть строка, содержащая одну обратную косую черту. print печатает только то, что есть в строке. Это не делает никакой дополнительной интерпретации.   -  person melpomene    schedule 22.01.2019
comment
Я обновил вопрос.   -  person Claude    schedule 22.01.2019
comment
Пожалуйста, не спрашивайте меня об источнике строки, это всего лишь образец строки. - нет, источник действительно имеет значение. Если источником является ваш исходный код, практически невозможно вручную удвоить все обратные косые черты в исходном коде. Если строка приходит откуда-то еще, Perl отображает ее как есть.   -  person Corion    schedule 22.01.2019
comment
Я полагаю, вы, ребята, правы с важностью источника. Спасибо, что помогли мне разобраться в этой ситуации. В этом случае мой live-скрипт должен работать, потому что источником строк является файл. У меня еще нет окончательной версии, поэтому я могу проверить правильно. После проверки другой темы кажется, что в perl нет простого способа предотвратить интерпретацию двойной обратной косой черты как одиночной обратной косой черты.   -  person Claude    schedule 22.01.2019


Ответы (1)


У меня есть эта примерная строка, содержащая 2 обратных слэша. ...

my $string = "use Ppppp\\Ppppp;";

Извините, но вы ошиблись — эта строка содержит только одну обратную косую черту*, так как \\ — это escape-последовательность в строках с двойными (и одинарными) кавычками, которая создает одиночную обратную косую черту. См. также "Операторы Quote и Quote-like" в perlop. Если ваша строка действительно содержит две обратные косые черты, вам нужно написать "use Ppppp\\\\Ppppp;" или использовать heredoc, например:

chomp( my $string = <<'ENDSTR' );
use Ppppp\\Ppppp;
ENDSTR

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

my $string = "use Ppppp\\Ppppp;";
# option 1
use Data::Dumper;
$Data::Dumper::Useqq=1;
$Data::Dumper::Terse=1;
print Dumper($string);
# option 2
use Data::Dump;
dd $string;
# option 3
use B;
print B::perlstring($string);

Каждый из них будет печатать "use Ppppp\\Ppppp;". (Конечно, доступны и другие модули. Лично мне нравится Data::Dump. Data::Dumper — это основной модуль.)

Использование одного из этих модулей также является лучшим способом проверить, что ваша $string переменная на самом деле содержит.

Если это все еще не соответствует вашим потребностям: предыдущее редактирование вашего вопроса гласило: "Как я могу правильно экранировать все специальные символы, включая обратную косую черту?" — вам нужно будет указать полный список этих символов. вы считаете спец. Вы можете сделать что-то вроде этого, например:

use 5.014; # for s///r
my $string = "use Ppppp\\Ppppp;";
print $string=~s/(?=[\\])/\\/gr;

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

* Обновление: Так что здесь я не кажусь слишком педантичным: конечно, исходный код Perl содержит две обратные косые черты. Но есть разница между буквальным исходным кодом и тем, что в конечном итоге содержит строка Perl, точно так же, как строка "Foo\nBar" содержит символ новой строки вместо двух буквальных символов \ и n.

Для полноты картины, как уже обсуждалось в комментариях: \Q\E (он же quotemeta) в первую очередь предназначен для экранирования любых специальных символов, которые могут быть специфическими для регулярных выражений (все символы ASCII, не соответствующие /[A-Za-z_0-9]/), поэтому он также экранирует пробелы и точку с запятой.

Поскольку вы упоминаете внешние файлы: если вы читаете строку, такую ​​как use Ppppp\\Ppppp;, из внешнего файла, то строка Perl будет содержать две обратные косые черты, а если вы print, она также покажет две обратные косые черты. Но если вы хотите представить эту строку как исходный код Perl, вам нужно написать "use Ppppp\\\\Ppppp;" (или использовать один из других методов из вопроса, на который вы ссылались ).

person haukex    schedule 22.01.2019
comment
Спасибо за ваш ответ. Ваши советы (и другие) помогли мне понять, как обстоят дела с двойным обратным слэшем. - person Claude; 22.01.2019
comment
Re Извините, но вы ошиблись - эта строка содержит только одну обратную косую черту. Лучшая формулировка: на самом деле это строковый литерал с двумя обратными косыми чертами; строка, которую он создает, имеет только одну. - person ikegami; 23.01.2019