Есть ли способ выполнить экранирование строки POSIX из Tcl?
Фон:
У меня есть список произвольных имен файлов в списке Tcl. Мне нужно расширить список, чтобы вставить его во фрагмент оболочки, который впоследствии будет выполняться произвольной оболочкой POSIX (bash, dash, posh и т. д.) с помощью команды «sh -c».
Вот пример, иллюстрирующий проблему:
#!/usr/bin/tclsh
set targets {with\ spaces has"stray'quotes has{brackets} $not_a_variable \[escaped_braces\] (not_a_subshell) weird\ \{|#^$(}
set shell_fragment {
something
some_command $targets
something else
}
puts [subst $shell_fragment]
Результатом вышеизложенного являются имена с экранированием Tcl:
something
some_command with\ spaces has"stray'quotes has{brackets} $not_a_variable \[escaped_braces\] (not_a_subshell) weird\ \{|#^$(
something else
Принимая во внимание, что мне нужно, чтобы он выглядел правильно, примерно так (экранирование оболочки POSIX):
something
some_command with\ spaces has\"stray\'quotes has{brackets} \$not_a_variable [escaped_braces] \(not_a_subshell\) weird\ {\|\#^\$\(
something else
Мысли:
Вот несколько способов, которыми я могу представить решение этой проблемы, которые я действительно не хочу делать:
В Bash есть средство форматирования %q для printf, которое делает то, что я хочу. Я мог бы выполнять вызовы bash один раз для каждого имени файла, чтобы воспользоваться этой возможностью, но это 1) довольно большой возврат и 2) вводит зависимость от bash, чего я не хочу делать.
Реализовать экранирование оболочки в соответствии с правилами экранирования оболочки POSIX. Это, очевидно, сработает, но я бы не хотел изобретать велосипед. Я нашел «простой» способ сделать это, рассылая спам кавычками, но это делает отладку ужасной и значительно сокращает доступную длину командной строки:
Примеры «плохих» способов сделать это:
proc posix_escape_via_bash {name} {
return [exec bash -c {printf %q "$0"} $name]
}
proc posix_escape_via_spamming_quotes {name} {
set escaped {}
foreach char [split $name {}] {
switch $char {
' {lappend escaped {\'}}
default {lappend escaped '$char'}
}
}
return [join $escaped {}]
}
Итак, еще раз: есть ли способ выполнить escape-оболочку POSIX для строки из Tcl? Меня бы больше всего устроил "стандартный" способ сделать это, если он есть, но я бы также доволен нестандартной библиотекой Tcl или даже способом сделать это из C, чтобы я мог вызывать это из Tcl.
posix_escape_via_bash
столкнется с проблемами, если$name
начинается с символа перенаправления, такого как>
.exec
усыпан подводными камнями… - person Donal Fellows   schedule 21.06.2012