Tim Scott
Tim Scott

Reputation: 77

How to set a TCL variable as a varible in a bash script

So my goal is to take a variable that is in my TCL file and pass it to my shell script for it to be able to use. Right now I am able to echo to get the result of my variable but I cannot for some reason set that result to a variable in my bash script.

Here is an example of my TCL script:

set file_status "C"

Here is what I have for my bash script:

echo 'source example.tcl; foreach _v {file_status } {puts "\"[set $_v]\""}' | tclsh
file_status='source example.tcl; foreach _v {file_status } {puts "\"[set $_v]\""}' | tclsh
echo $file_status

So the first echo statement above works but after I set the file_status variable for some reason the second echo statement doesn't work.

Upvotes: 0

Views: 1150

Answers (2)

Donal Fellows
Donal Fellows

Reputation: 137767

Doing it in general requires very complex code; Tcl variables are capable of holding arbitrary data (including full binary data) and don't have length restrictions, whereas Shell is a lot more restricted. But it's possible to do something for the common cases where the values are plain text without NULs. (C would be an excellent example of such a value.)

When passing to a subprocess, by far the easiest way is to use an environment variable:

set the_status "C"
set env(file_status) $the_status
exec bash -c {echo "file status is $file_status"} >@stdout

That has length restrictions, but it's extremely easy.

If you're sending the variable to some other process, your best bet is to write a little script (here, I'm sending it to stdout):

puts [format {file_status='%s'} [string map {"'" "'\''"} $the_status]]

That is producing a script that just sets the variable. (string map is turning single quotes into something that works inside single quotes; everything else doesn't need conversion like that.) You run the script in the shell with eval or source/. (depending on whether it is in a string or in a file).

Very large data should be moved around inside a file or via a pipe. It needs much more thought in general.

Upvotes: 1

glenn jackman
glenn jackman

Reputation: 247142

I would output shell syntax from Tcl and source it into your running shell:

Given

$ echo 'source example.tcl; foreach var {file_status} {puts "$var=\"[set $var]\""}' | tclsh
file_status="C"

then

source <(echo 'source example.tcl; foreach var {file_status} {puts "$var=\"[set $var]\""}' | tclsh)
declare -p file_status

outputs

declare -- file_status="C"

Using /bin/sh, you could:

var_file=$(mktemp)
echo ... | tclsh > "$var_file"
source "$var_file"
rm "$var_file"

Upvotes: 0

Related Questions