質問
TCLスクリプトの形で出力を生成しているユーティリティ(たまたまPythonにあります)を書いています。 Pythonに任意の文字列変数(Unicodeではない)を考えると、次のようなTCLラインを作成したい
set s something
... TCL変数を設定します」s
「その正確な文字列に、奇妙なキャラクターがその中にあるものに関係なく。奇妙になりすぎずに、出力を必要以上に厄介にしたくありません。まともなアプローチはそうだと思います
文字列が空でなく、アルファナメリックのみが含まれている場合、そして一部の文字は
.-_
(しかし、間違いなくそうではありません$"{}\
)その後、それを使用することができます。印刷可能な文字のみが含まれており、ダブルクォートや巻き毛のブレースが含まれていない場合(そしてバックスラッシュで終わりません)、単純に置く
{}
その周りに;それ以外の場合は、置きます
""
使用した後の周り\
逃げる"
{
}
\
$
[
]
、 と\nnn
非印刷キャラクターの脱出。
質問:それは、二重引用符の中で逃げる必要があるキャラクターの完全なセットですか?ドキュメントでこれを見つけることができません。そして、私は何かを逃しましたか(たとえばで終わることができないという文字列を見逃しそうになりました)。
引用できる他の文字列がたくさんあることを知っています {}
, 、しかし、それらを簡単に識別することは難しいようです。また、TCL出力に文字通り存在することを気にしない場合、非印刷文字(特にNewline)は(2)では問題ないようです。
解決
あなたは本当に2つのルールしか必要ありません、
- 巻き毛の装具を逃がします
- 出力をカーリーブレースで包みます
NewLines、非印刷可能な文字などを心配する必要はありません。それらは文字通りの文字列で有効であり、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}
}
編集あなたのコメントに照らして、あなたは次のことをすることができます:
- エスケープ
[]
{}
と$
- 出力全体をラップします
set s [subst { $output } ]
TCLの美しさは、それが非常にシンプルな文法を持っているということです。上記の3つを逃れるために必要なキャラクターは他にありません。
編集2 最後に試してみてください。
合格した場合 subst
いくつかのオプション、あなたは逃げる必要があります \
と {}
set s [subst -nocommands -novariables { $output } ]
ただし、印刷可能でない文字を逃げたコードに変換するには、正規表現を考え出す必要があります。
幸運を!
他のヒント
TCLには、二重引用文字列の中にある場合、メタカラクターはほとんどありません。それらのすべてを引用することで、それらの前にバックスラッシュを置くことで引用できます。引用しなければならないキャラクターはそうです \
自体、 $
と [
, 、しかし、それも引用することは良い習慣と考えられています ]
, {
と }
スクリプト自体が組み込み可能になるように。 (TCL自身 list
コマンドはこれを行いますが、実際には二重引用符をラップしないため、バックスラッシュも処理し、「素敵な」文字列で他のテクニックを使用しようとします。これを行うためのアルゴリズムがありますが、私はあなたのコードにそれほど複雑さを悩ませないことをお勧めします。単純なユニバーサルルールは、正しいコーディングの方がはるかに優れています。)
2番目のステップは、データをTCLに入れることです。ファイルを生成している場合、最良のオプションはUTF-8として記述し、 -encoding
tclsh/wishまたはへのオプション source
エンコーディングとは何かを明示的に述べるようにコマンド。 (同じプロセス内にある場合は、UTF-8データを文字列に記入して評価します。ジョブが完了します。)そのオプション(TCL 8.5で導入)は、この種の問題に特に対処するためのものです。
source -encoding "utf-8" theScriptYouWrote.tcl
それが不可能な場合は、引用を追加することに戻る必要があります。最良のことは、ASCIIサポートしか利用できないと仮定し(最も低い一般的な分母)、他のすべてを引用することです 最初の段落に記載されている引用への別のステップとして. 。引用するには、すべてのユニコード文字をu+00080からフォームのエスケープシーケンスに変換します \uXXXX
ここで、xxxxは正確に4ヘクスの数字です[1] そして、他の2つは文字通りのキャラクターです。使用しないでください \xXX
フォーム、それはいくつかの「驚くべき」ミスフェイター(悲しいかな)を持っています。
[1] TCLには、基本的な多言語ペインの外で文字を処理することについてのオープンバグがあります。 部 そのことはそれです \u
フォームは対処できません。幸いなことに、BMP以外のキャラクターは、実際にはまだかなりまれです。
それを正しく行うには、Python文字列のエンコード、通常はsys.getDefaultEncoding()を指定する必要があります。それ以外の場合は、TCLに翻訳するときにエンコーディングをめちゃくちゃにするかもしれません。
文字列にバイナリデータがあり、結果としてTCLバイナリ文字列が必要な場合は、常に機能します。
data = "".join("\\u00%02x" % ord(c) for c in mystring)
tcltxt = "set x %s" % data
しかし、16進投げのように見えますが、それはヘックスダンプです...
UTF-8のような特別なエンコードを使用する場合、エンコードConvertfrom/Converttoと適切なPython Idiomを使用することで、それを少し強化できます。
data = "".join("\\u00%02x" % ord(c) for c in myutf8string)
tcltext = "set x [encoding convertfrom utf-8 %s]" % data
もちろん、これを少し改良することができます。すべての非特別文化のエンコードを避けますが、上記は安全です。