19

TCLスクリプトの形式で出力を生成するユーティリティ(たまたまPythonにあります)を書いています。Pythonで任意の文字列変数(Unicodeではない)を指定すると、次のようなTCL行を生成したい

set s something

... これにより、TCL 変数 ' s' がその文字列に正確に設定されます。奇妙になりすぎないように、出力を必要以上に乱雑にしたくありません。まともなアプローチは

  1. 文字列が空ではなく、英数字のみを含み、いくつかの文字が含まれている場合.-_(しかし絶対$"{}\にそうではない)、そのまま使用できます。

  2. 印刷可能な文字のみが含まれ、二重引用符や中括弧が含まれていない (およびバックスラッシュで終わっていない) 場合は、単純に囲みます{}

  3. それ以外の場合は、 のエスケープと非印刷文字のエスケープを""使用した後に前後に置きます。\" { } \ $ [ ]\nnn

質問: 二重引用符内でエスケープする必要がある文字の完全なセットですか? ドキュメントでこれを見つけることができません。そして、私は何かを見逃しましたか(たとえば、(2)の文字列が \ で終わることはできないことをほとんど見逃していました)。

で引用できる文字列が他にもたくさんあることは知っていますが {}、それらを簡単に識別するのは難しいようです。また、非印刷文字 (特に改行) は、TCL 出力に文字通り存在することを気にしないのであれば、(2) で問題ないようです。

4

4 に答える 4

17

本当に必要なルールは 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}
}

編集 コメントに照らして、次のことができます。

  • 逃げ[] {}$
  • 出力全体をラップしますset s [subst { $output } ]

Tcl の優れた点は、文法が非常に単純なことです。上記の 3 以外にエスケープが必要な文字はありません。

編集 2最後にもう一度。

いくつかのオプションを渡す場合subst、エスケープするだけで済みます\{}

set s [subst -nocommands -novariables { $output } ]

ただし、印刷できない文字をエスケープされたコードに変換するには、正規表現を考え出す必要があります。

幸運を!

于 2011-03-14T17:39:51.320 に答える
6

二重引用符で囲まれた文字列の中に入ると、Tcl にはメタ文字がほとんどなく、バックスラッシュを前に置くことですべてを引用できます。引用しなければならない文字は\それ自体、$およびですが、スクリプト自体を埋め込み可能にするために、および[も引用することをお勧めします。(Tcl 独自のコマンドはこれを行いますが、実際には二重引用符をラップしないため、バックスラッシュも処理し、「適切な」文字列に対して他の手法を使用しようとします。これを行うためのアルゴリズムがありますが、気にしないことをお勧めします。コードが非常に複雑であるため、正しいコーディングには単純な普遍的なルールの方がはるかに優れています。)]{}list

2 番目のステップは、データを Tcl に取り込むことです。ファイルを生成する場合、最適なオプションは、ファイルを UTF-8 として記述し、-encodingtclsh/wish またはsourceコマンドのオプションを使用して、エンコーディングが何であるかを明示的に示すことです。(同じプロセス内にいる場合は、UTF-8 データを文字列に書き込み、それを評価します。ジョブは完了です。) そのオプション (Tcl 8.5 で導入) は、特にこの種の問題に対処するためのものです。

source -encoding "utf-8" theScriptYouWrote.tcl

それが不可能な場合は、フォールバックして追加の引用を追加する必要があります。最善の方法は、利用可能な ASCII サポート (適切な最小公分母) しかないと仮定し、他のすべてを最初の段落で説明した引用とは別のステップとして引用することです。引用するには、すべての Unicode 文字を U+00080 から次の形式のエスケープ シーケンスに変換します\uXXXX。ここで、XXXX は正確に 4 桁の 16 進数[1]であり、他の 2 つはリテラル文字です。このフォームには「驚くべき」誤機能があるため、使用しないでください\xXX(悲しいかな)。


[1] Basic Multilingual Pane の外にある文字の処理に関して、Tcl に未解決のバグがあり、その一部は、\uフォームが対応できないことです。幸いなことに、非 BMP 文字は実際にはまだかなりまれです。

于 2011-03-15T09:06:36.300 に答える
2

これを正しく行うには、Python文字列が含まれるエンコーディング(通常はsys.getdefaultencoding())も指定する必要があります。そうしないと、Tclに変換するときにエンコーディングが文字化けする可能性があります。

文字列にバイナリデータがあり、結果としてTclバイナリ文字列が必要な場合、これは常に機能します。

data = "".join("\\u00%02x" % ord(c) for c in mystring)
tcltxt = "set x %s" % data

16進ダンプのように見えますが、まあ、それは16進ダンプです...

UTF-8のような特別なエンコーディングを使用する場合は、エンコーディングconvertfrom / converttoと適切なPythonイディオムを使用して、それを少し強化できます。

data = "".join("\\u00%02x" % ord(c) for c in myutf8string)
tcltext = "set x [encoding convertfrom utf-8 %s]" % data

もちろん、これを少し改良して、すべての非特殊文字の\ uエンコーディングを回避することもできますが、上記はどのような場合でも安全です。

于 2011-03-14T18:59:25.047 に答える