tcl quoting

Cita de cadena general para TCL



quoting (3)

Estoy escribiendo una utilidad (que está en Python) que está generando resultados en forma de un script TCL. Dada una variable de cadena arbitraria (no unicode) en el pitón, quiero producir una línea TCL como

set s something

... que establecerá la variable TCL '' s '' en esa cadena exacta, independientemente de los caracteres extraños que haya en ella. Sin volverme demasiado raro, no quiero que la salida sea más desordenada de lo necesario. Creo que un enfoque decente es

  1. si la cadena no está vacía y contiene solo caracteres alfanuméricos, y algunos caracteres como .-_ (pero definitivamente no es $"{}/ ), entonces se puede usar como está;

  2. si solo contiene caracteres imprimibles y no tiene comillas dobles ni llaves (y no termina en barra invertida), simplemente coloque {} a su alrededor;

  3. de lo contrario, "" a su alrededor después de usar / escapes para " { } / $ [ ] , y /nnn escapes para caracteres que no se imprimen.

Pregunta: ¿es el conjunto completo de caracteres que necesitan escaparse entre comillas dobles? No puedo encontrar esto en los documentos. Y si me perdí algo (casi me olvido de que las cadenas para (2) no pueden terminar en / por ejemplo).

Sé que hay muchas otras cadenas que pueden ser citadas por {} , pero parece difícil identificarlas fácilmente. Además, parece que los caracteres que no se imprimen (en particular, nueva línea) están bien con (2) si no les importa que estén literalmente presentes en la salida TCL.


Para hacerlo bien, también debe especificar la codificación en la que se encuentra su cadena de python, normalmente sys.getdefaultencoding (). De lo contrario, podría distorsionar las codificaciones al traducirlo a Tcl.

Si tiene datos binarios en su cadena y quiere cadenas binarias Tcl como resultado, esto siempre funcionará:

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

Sin embargo, se verá como un volcado de hex, pero bueno, es un volcado de hex ...

Si usa una codificación especial como UTF-8, puede mejorarla un poco utilizando la conversión de conversión / conversión y el idioma de Python apropiado.

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

Por supuesto, puede refinar esto un poco, evitando la codificación / u de todos los caracteres no especiales, pero lo anterior es seguro en cualquier caso.


Realmente solo necesitas 2 reglas,

  • Escapar de llaves
  • Envuelva la salida en llaves

No necesita preocuparse por las nuevas líneas, los caracteres no imprimibles, etc. Son válidos en una cadena literal, y TCL tiene un excelente soporte de 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} }

Editar A la luz de tu comentario, puedes hacer lo siguiente:

  • escapar [] {} y $
  • envuelva la salida completa en el set s [subst { $output } ]

La belleza de Tcl es que tiene una gramática muy simple. No hay otros personajes además de los 3 anteriores necesarios para escapar.

Editar 2 Un último intento.

Si pasa varias opciones, solo tendrá que escapar / y {}

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

Sin embargo, deberá crear una expresión regular para convertir caracteres no imprimibles a sus códigos de escape.

¡Buena suerte!


Tcl tiene muy pocos metacaracteres una vez que estás dentro de una cadena de comillas dobles, y todos ellos pueden citarse poniendo una barra invertida delante de ellos. Los caracteres que debe citar son / sí, $ y [ , pero se considera una buena práctica también para citar ] , { y } para que el script en sí sea incrustado. (El propio comando de list Tcl hace esto, excepto que en realidad no incluye las comillas dobles, por lo que también maneja las barras invertidas y también intentará usar otras técnicas en cadenas "agradables". Hay un algoritmo para hacer esto, pero no aconsejo molestándose con tanta complejidad en su código; las reglas universales simples son mucho mejores para la codificación correcta.)

El segundo paso es obtener los datos en Tcl. Si está generando un archivo, su mejor opción es escribirlo como UTF-8 y usar la opción -coding para tclsh / wish o para el comando de source para indicar explícitamente qué es la codificación. (Si está dentro del mismo proceso, escriba los datos UTF-8 en una cadena y evalúe eso. Trabajo finalizado.) Esa opción (introducida en Tcl 8.5) es específicamente para tratar este tipo de problema:

source -encoding "utf-8" theScriptYouWrote.tcl

Si eso no es posible, tendrá que volver a agregar cotizaciones adicionales. Lo mejor es asumir que solo tiene soporte ASCII disponible (un buen denominador común más bajo) y citar todo lo demás como un paso separado a la cita que se describe en el primer párrafo . Para citar, convierta cada carácter Unicode de U + 00080 a una secuencia de escape de la forma /uXXXX donde XXXX son exactamente cuatro dígitos hexadecimales [1] y los otros dos son caracteres literales. No use la forma /xXX , ya que tiene algunas características "sorprendentes" (por desgracia).

[1] Hay un error abierto en Tcl sobre el manejo de caracteres fuera del Panel Multilingüe Básico, parte del cual es que la forma /u no puede hacer frente. Afortunadamente, los caracteres que no son BMP son todavía bastante raros en la práctica.