Подтвердить что ты не робот

Общее строковое цитирование для TCL

Я пишу утилиту (которая, случается, находится в python), которая генерирует вывод в виде TCL script. Учитывая некоторую произвольную строковую переменную (не unicode) в python, я хочу создать линию TCL, например

set s something

... который установит переменную TCL 's' этой точной строке, независимо от того, какие странные символы в ней. Не становясь слишком странным, я не хочу, чтобы результат был бесполезным, чем нужно. Я считаю, что достойный подход

  • если строка не пуста и содержит только буквенно-цифровые символы, а некоторые символы типа .-_ (но определенно не $"{}\), то ее можно использовать как-is;

  • если он содержит только печатные символы, а не двойные кавычки или фигурные фигурные скобки (и не заканчивается обратным слэшем), просто поместите {} вокруг него;

  • положите "" вокруг него после использования \ экранов для " { } \ $ [ ], а \nnn -печатать символы.

Вопрос: есть ли полный набор символов, которые нужно избегать внутри двойных кавычек? Я не могу найти это в документах. И я что-то пропустил (я почти пропустил, что строки для (2) не могут закончиться, например,).

Я знаю, что есть много других строк, которые могут быть указаны {}, но их трудно идентифицировать легко. Кроме того, похоже, что непечатные символы (в частности, новая строка) в порядке с (2), если вы не возражаете, чтобы они буквально присутствовали в выводе TCL.

4b9b3361

Ответ 1

Вам действительно нужны только 2 правила,

  • Скрыть фигурные скобки
  • Оберните вывод в фигурные скобки

Вам не нужно беспокоиться о новостях, непечатаемых символах и т.д. Они действительны в строковой литературе, а TCL имеет отличную поддержку Unicode.

set s { 
this is
a 
long 
string. I have $10 [10,000 cents] only curly braces \{ need \} to be escaped.
\t is not  a real tab, but '    ' is. "quoting somthing" :
{matchin` curly braces are okay, list = string in tcl}
}

Изменить В свете вашего комментария вы можете сделать следующее:

  • escape [] {} и $
  • завершает весь вывод в set s [subst { $output } ]

Красота Tcl - это очень простая грамматика. Нет других персонажей, кроме 3, которые должны были быть экранированы.

Изменить 2 Последняя попытка.

Если вы передадите subst некоторые параметры, вам нужно будет только \ и {}

set s [subst -nocommands -novariables { $output } ]

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

Удачи!

Ответ 2

Tcl имеет очень мало метасимволов после того, как вы находитесь внутри строки с двумя кавычками, и все они могут быть указаны, помещая обратную косую черту перед ними. Символы, которые вы должны процитировать, - это \, $ и [, но считали хорошей практикой также цитировать ], { и }, чтобы сам script был вложен. (Команда Tcl own list делает это, за исключением того, что она фактически не обертывает двойные кавычки, поэтому она также обрабатывает обратную косую черту, а также пытается использовать другие методы для "хороших" строк. Там есть алгоритм для этого, но я советуйте не беспокоиться о такой сложности в коде, простые универсальные правила намного лучше подходят для правильного кодирования.)

Второй шаг - получить данные в Tcl. Если вы создаете файл, лучше всего написать его как UTF-8 и использовать параметр -encoding для tclsh/wish или для команды source, чтобы явно указать, что такое кодировка. (Если вы находитесь внутри одного и того же процесса, напишите данные UTF-8 в строку и оцените это. Job Done.) Этот параметр (введенный в Tcl 8.5) специально предназначен для решения этой проблемы:

source -encoding "utf-8" theScriptYouWrote.tcl

Если это невозможно, вам придется вернуться к добавлению дополнительного цитирования. Лучше всего предположить, что у вас есть только доступная поддержка ASCII (хороший самый низкий общий знаменатель) и цитируйте все остальное как отдельный шаг к цитированию, описанному в первом абзаце. Чтобы процитировать, преобразуйте каждый символ Юникода из U + 00080 в escape-последовательность формы \uXXXX, где XXXX - это ровно четыре шестнадцатеричных цифры [1] а остальные два являются буквальными символами. Не используйте форму \xXX, так как у нее есть некоторые "удивительные" ошибки (увы).


[1] В Tcl есть открытая ошибка в отношении обработки символов вне базовой многоязычной панели, частью которой является то, что форма \u не может справиться. К счастью, символы, отличные от BMP, на практике по-прежнему редко встречаются.

Ответ 3

Чтобы сделать это правильно, вы также должны указать кодировку, в которой находится ваша строка python, обычно sys.getdefaultencoding(). В противном случае вы можете использовать кодировки при переводе в Tcl.

Если у вас есть двоичные данные в вашей строке и вам нужны двоичные строки Tcl, в результате это всегда будет работать:

data = "".join("\\u00%02x" % ord(c) for c in mystring)
tcltxt = "set x %s" % data

Будет выглядеть как шестнадцатеричный дамп, но, ну, это шестнадцатеричный дамп...

Если вы используете какую-либо специальную кодировку, такую ​​как UTF-8, вы можете немного увеличить ее, используя кодировку convertfrom/convertto и соответствующую идиому Python.

data = "".join("\\u00%02x" % ord(c) for c in myutf8string)
tcltext = "set x [encoding convertfrom utf-8 %s]" % data

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