Search code examples
tclquoting

Tcl quoting proc to sanitise string to pass to other shells


I want to pass a dict value to another shell (in my application it passes through a few 'shell' levels), and the dict contains characters (space, double quotes, etc) that cause issues.

I can use something like ::base64::encode -wrapchar $dict and the corresponding ::base64::decode $str and it works as expected but the result is, of course, pretty much unreadable.

However, for debugging & presentation reasons I would prefer an encoded/sanitised string that resembled the original dict value inasmuch as reasonable and used a character set that avoids spaces, quotes, etc. So, I am looking for something like ::base64 mapping procs but with a lighter touch.

Any suggestions would be appreciated.


Solution

  • You can make lighter-touch quoting schemes using either string map or regsub to do the main work.

    Here's an example of string map:

    set input "O'Donnell's Bait Shop"
    set quoted '[string map {' {'\''}} $input]'                                                 ; #'# This comment just because of stupid Stack Overflow syntax highlighter
    puts $quoted
    # ==> 'O'\''Donnell'\''s Bait Shop'
    

    Here's an example of regsub:

    set input "This uses a hypothetical quoting of some letters"
    set quoted <[regsub -all {[pqr]} $input {«&»}]>
    puts $quoted
    # ==> <This uses a hy«p»othetical «q»uoting of some lette«r»s>
    

    You'll need to decide what sort of quoting you really want to use. For myself, if I was going through several shells, I'd be wanting to avoid quoting at all (because it is difficult to get right) and instead find ways to send the data in some other way, perhaps over a pipeline or in a temporary file. At a pinch, I'd use an environment variable, as shells tend to not mess around with those nearly as much as arguments.