Question

Je l'écriture d'un utilitaire (qui se trouve être en python) qui génère la sortie sous la forme d'un script TCL. Étant donné une variable chaîne arbitraire (non unicode) dans le python, je veux produire une ligne TCL comme

set s something

... qui va définir la variable TCL « de s » à cette chaîne exacte, quel que soit ce que les personnages étranges sont là. Sans être trop bizarre, je ne veux pas faire le messier de sortie que nécessaire. Je crois qu'une approche décente est

  1. si la chaîne est vide et ne contient que des caractères alphanumériques, et certains personnages comme .-_ (mais certainement pas $"{}\) alors il peut être utilisé tel quel;

  2. si elle ne contient que des caractères imprimables et sans guillemets doubles ou accolades (et ne se termine pas par backslash), puis il suffit de mettre {} autour;

  3. Sinon, mettez "" autour d'elle après l'utilisation \ échappe pour " { } \ $ [ ], et échappe \nnn pour les caractères non-impression.

Question: est que l'ensemble des caractères qui ont besoin d'échapper à l'intérieur des guillemets doubles? Je ne trouve pas cela dans les documents. Et ai-je raté quelque chose (je presque manqué que les chaînes pour (2) ne peut pas se terminer par \ par exemple).

Je sais qu'il ya beaucoup d'autres chaînes qui peuvent être proposés par {}, mais il semble difficile de les identifier facilement. , Il ressemble également à des caractères non-impression (en particulier, saut de ligne) sont OK avec (2) si vous ne les dérange pas d'être littéralement présent dans la sortie TCL.

Était-ce utile?

La solution

Vous avez vraiment besoin de 2 règles,

  • échapper accolades
  • Wrap la sortie entre accolades

Vous n'avez pas à vous soucier de nouvelles lignes, des caractères non imprimables, etc. Ils sont valides dans une chaîne littérale, et TCL a une excellente prise en charge 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}
}

Modifier À la lumière de votre commentaire, vous pouvez faire ce qui suit:

  • évasion [] {} et $
  • envelopper toute la production dans set s [subst { $output } ]

La beauté de Tcl est un a une grammaire très simple. Il n'y a pas d'autres personnages en plus les 3 ci-dessus devait être échappé.

Modifier 2 Un dernier essai.

Si vous passez subst quelques options, vous aurez seulement besoin d'échapper \ et {}

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

Vous auriez besoin de trouver une expression régulière pour convertir les caractères non imprimables à leurs codes échappées cependant.

Bonne chance!

Autres conseils

Tcl a très peu métacaractères une fois que vous êtes à l'intérieur d'une chaîne entre guillemets, et ils peuvent tous être cité en mettant une barre oblique inverse devant eux. Les caractères que vous devez citer sont \ lui-même, et $ [, mais il est considéré comme une bonne pratique de citer également ], { et } de telle sorte que le script est intégrable lui-même. (Propre commande list Tcl fait cela, sauf qu'il ne fait pas envelopper les guillemets doubles il gère également antislashs et il essaiera également d'utiliser d'autres techniques sur les chaînes de « belles ». Il y a un algorithme pour le faire, mais je conseille de ne pas prendre la peine avec cette complexité beaucoup dans votre code,. règles universelles simples sont beaucoup mieux pour le codage correct)

La deuxième étape consiste à obtenir les données en Tcl. Si vous générez un fichier, votre meilleure option est d'écrire comme UTF-8 et utiliser l'option -encoding à tclsh / désir ou à la commande source pour indiquer explicitement ce que l'encodage est. (Si vous êtes dans le même processus, écriture données UTF-8 dans une chaîne et d'évaluer ce travail..) Cette option (introduite dans Tcl 8.5) est spécifiquement pour traiter ce genre de problème:

source -encoding "utf-8" theScriptYouWrote.tcl

Si ce n'est pas possible, vous allez devoir revenir à ajouter en citant supplémentaires. La meilleure chose est de supposer alors vous avez seulement le soutien ASCII disponible (un bon plus petit dénominateur commun) et tout autre citation comme une étape distincte à la citation décrit dans le premier paragraphe . Pour citer, convertir tous les caractères Unicode de U + 00080 jusqu'à une séquence d'échappement de la forme \uXXXX où XXXX sont quatre chiffres hex exactement [1] et les deux autres sont des caractères littéraux. Ne pas utiliser le formulaire de \xXX, comme cela a quelques mauvaises fonctionnalités « surprenant » (hélas) de.


[1] Il y a un bug ouvert Tcl sur les caractères de manipulation à l'extérieur du base multilingue volet, partie qui est que la forme \u ne peut pas faire face. Heureusement, les caractères non-BMP sont encore assez rares dans la pratique.

Pour le faire correctement vous devez également spécifier l'encodage de votre chaîne de python est, généralement sys.getdefaultencoding (). Sinon, vous pourriez garble encodages lors de la traduction à Tcl.

Si vous avez des données binaires dans votre chaîne et que vous voulez Tcl chaînes binaires en conséquence ce sera toujours le travail:

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

ressemble à un vidage hexadécimal bien, mais bon, il est un vidage hexadécimal ...

Si vous utilisez un encodage spécial comme UTF-8, vous pouvez améliorer un peu ce en utilisant le codage ConvertFrom / convertto et l'idiome Python approprié.

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

Vous pouvez bien sûr affinez cela un peu, en évitant le \ u encodage de tous les caractères non spéciaux, mais ce qui précède est sûr en tout cas.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top