Tcl 内から文字列に対して POSIX シェル エスケープを実行する方法はありますか?
バックグラウンド:
Tcl リストに任意のファイル名のリストがあります。「sh -c」を実行して任意の POSIX シェル (bash、dash、posh など) によって後で実行されるシェル フラグメントに貼り付けるには、リストを展開する必要があります。
この問題を示す例を次に示します。
#!/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には、私が望むことを行うprintfへの%qフォーマッターがあります。この機能を利用するために、ファイル名ごとに 1 回 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 {}]
}
繰り返しますが、Tcl内から文字列に対してPOSIXシェルエスケープを実行する方法はありますか? これを行うための「標準的な」方法があればそれが一番嬉しいですが、非標準の Tcl ライブラリ、または C からこれを行う方法さえあれば、Tcl から呼び出すことができます。 .