Общее строковое цитирование для TCL
Я пишу утилиту (которая, случается, находится в python), которая генерирует вывод в виде TCL script. Учитывая некоторую произвольную строковую переменную (не unicode) в python, я хочу создать линию TCL, например
set s something
... который установит переменную TCL 's
' этой точной строке, независимо от того, какие странные символы в ней. Не становясь слишком странным, я не хочу, чтобы результат был бесполезным, чем нужно. Я считаю, что достойный подход
-
если строка не пуста и содержит только буквенно-цифровые символы, а некоторые символы типа .-_
(но определенно не $"{}\
), то ее можно использовать как-is;
-
если он содержит только печатные символы, а не двойные кавычки или фигурные фигурные скобки (и не заканчивается обратным слэшем), просто поместите {}
вокруг него;
-
положите ""
вокруг него после использования \
экранов для "
{
}
\
$
[
]
, а \nnn
-печатать символы.
Вопрос: есть ли полный набор символов, которые нужно избегать внутри двойных кавычек? Я не могу найти это в документах. И я что-то пропустил (я почти пропустил, что строки для (2) не могут закончиться, например,).
Я знаю, что есть много других строк, которые могут быть указаны {}
, но их трудно идентифицировать легко. Кроме того, похоже, что непечатные символы (в частности, новая строка) в порядке с (2), если вы не возражаете, чтобы они буквально присутствовали в выводе TCL.
Ответы
Ответ 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
Конечно, вы можете немного уточнить это, избегая кодирования всех нестандартных символов, но в любом случае это безопасно.