有没有办法在 Tcl 中对字符串执行 POSIX shell 转义?
背景:
我在 Tcl 列表中有一个任意文件名的列表。我需要扩展列表以粘贴到稍后将由任意 POSIX shell(bash、dash、posh 等)通过执行“sh -c”执行的 shell 片段中。
这是一个说明问题的示例:
#!/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 shell 转义):
something
some_command with\ spaces has\"stray\'quotes has{brackets} \$not_a_variable [escaped_braces] \(not_a_subshell\) weird\ {\|\#^\$\(
something else
想法:
以下是我可以想象的一些我不想做的解决方法:
在 Bash 中,printf 有 %q 格式化程序,可以满足我的要求。我可以为每个文件名执行一次 bash 调用以利用此功能,但这 1) 是一个很大的后盾,并且 2) 引入了对 bash 的依赖,这是我不希望这样做的。
根据 POSIX shell 转义规则实现自己的 shell 转义。这显然可行,但我宁愿不重新发明轮子。我发现了一种“简单”的方法,通过发送垃圾引号来做到这一点,但这会使调试变得很糟糕,并大大减少了可用的命令行长度:
“坏”方法的例子:
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 {}]
}
再说一遍:有没有办法在 Tcl 中对字符串执行 POSIX shell 转义?如果有一个“标准”的方法,我会很高兴,但我也很高兴有一个非标准的 Tcl 库,甚至是从 C 中做到这一点的方法,所以我可以从 Tcl 调用它.