Prev: What is the best way to handle file names passed to a TCL script?
Next: How to calculate "elapsed time" and "functions execution time" in log file?
From: Ahmad on 5 Aug 2010 16:09 Hi, I'm reading a configuration file passed to my tcl script. This configuration file, could contain paths to certain files using environment variables: for example: file1_path $var1/$var2/${var3}/file.ext My script is parsing the config file, splitting each line to get key and value (path) of entries. But passing this path directly to tcl nees to be first converted to $env(...) I tried to use regsub to change all occurrences of cases like this, using: set a {var1/$var2/${var3}/nonVar/file.ext} set b [split $a '/'] regsub -all {$([^/]+)} \$env(\1) $b But I don't know why it's always returning $evn( ) What is wrong in my expression? Is there any easier way to interpret shell env vars? Thanks, Ahmad
From: Ahmad on 5 Aug 2010 17:47 I'm afraid I cannot understand. $var1, $var2, ... are random env vars names parsed from a config file. I need to interpret their corresponding value into my tcl script. Is that what do you mean? Thanks, Ahmad On Aug 5, 2:38 pm, "Gerald W. Lester" <Gerald.Les...(a)KnG- Consulting.net> wrote: > Ahmad wrote: > > Hi, > > > I'm reading a configuration file passed to my tcl script. > > > This configuration file, could contain paths to certain files using > > environment variables: for example: > > > file1_path $var1/$var2/${var3}/file.ext > > > My script is parsing the config file, splitting each line to get key > > and value (path) of entries. > > > But passing this path directly to tcl nees to be first converted to > > $env(...) > > > I tried to use regsub to change all occurrences of cases like this, > > using: > > > set a {var1/$var2/${var3}/nonVar/file.ext} > > set b [split $a '/'] > > regsub -all {$([^/]+)} \$env(\1) $b > > > But I don't know why it's always returning $evn( ) > > > What is wrong in my expression? > > > Is there any easier way to interpret shell env vars? > > Yes, depends on how safe you want to be. > > Least safe: > > Define a procedure which takes the file string (lets say file) which: > 1) defines a local variable (e.g. var1) for each env var (e.g. ::env(var1)) > 2) return a [subst -nocommand -nobackslash $file] > > Most safe: > Create a safe interp with all commands hidden except subst. > Define global variables (e.g. var1) for each env var (e.g. ::env(var1)) > evaluate [list subst -nocommand -nobackslash $file] in the safe interp > > -- > +------------------------------------------------------------------------+ > | Gerald W. Lester, President, KNG Consulting LLC | > | Email: Gerald.Les...(a)kng-consulting.net | > +------------------------------------------------------------------------+
From: Donald Arseneau on 5 Aug 2010 18:40 On Aug 5, 1:09 pm, Ahmad <ahmad.abdulgh...(a)gmail.com> wrote: > This configuration file, could contain paths to certain files using > environment variables: for example: > > file1_path $var1/$var2/${var3}/file.ext > > But passing this path directly to tcl nees to be first converted to > $env(...) How about copying environment variables into Tcl variables? proc substEnv { string } { set string [string map { {::} {} } $string] foreach {ev val} [array get ::env] { set $ev $val } return [subst -nocommand -nobackslashes $string] } Donald Arseneau
From: Ahmad on 5 Aug 2010 19:59 Thank you all, You taught me a lot indeed! Although the regsub way worked with me, I'm curious to know how "substEnv" function works. I'm trying to use: substEnv varName and it returns the same name. I tried with $varName, then it gave me error. Regards, Ahmad On Aug 5, 4:26 pm, Andreas Leitgeb <a...(a)gamma.logic.tuwien.ac.at> wrote: > Ahmad <ahmad.abdulgh...(a)gmail.com> wrote: > > set a {var1/$var2/${var3}/nonVar/file.ext} > > set b [split $a '/'] > > regsub -all {$([^/]+)} \$env(\1) $b > > But I don't know why it's always returning $evn( ) > > There's a whole bunch of little mistakes... ;) > -) first of all, you got the order of arguments for regsub > wrong - you mixed up the input string with the > substitute-pattern. > -) the search-pattern doesn't escape the $, so it will never > match anything (an unescaped dollar matches the end of string, > so nothing could follow it for a match) > You likely want the pattern {\$\{?([^/\}]+)\}?} instead, which > also discard eventual braces from braced variables. > -) you split for '/', but single quotes aren't special in tcl, so > you split by the literal 3-chars-string: quote,slash,quote, > which isn't found in $a, so you effectively get $a back, with > another level of list quoting, just as if you had written: > set b [list $a] > -) If you fixed the split command to split by slashes alone, then the > regexp-pattern would match everything after the first dollar, as > there wouldn't be any slashes left. Better leave the split out > completely, and apply the regsub on $a instead. > -) finally, the \1 in \$env(\1) get's prematurely substed. regsub doesn't > see the backslash-one sequence, but a character with code 1 (^A) > Use {$env(\1)} instead. > > regsub -all {\$\{?([^/\}]+)\}?} $a {$env(\1)} > > Others have posted solutions boiling down to copying the environment > variables into local variables of a procedure or even a new interpreter. > That's perhaps the simpler approach, though not necessarily the better. > And it takes a bit more than the naive approach, in order not to let the > iteration variables interfere with the variables created, if e.g. there > was a real envvar named "en" or "val".
From: Andreas Leitgeb on 6 Aug 2010 07:51
Ahmad <ahmad.abdulghany(a)gmail.com> wrote: > Although the regsub way worked with me, I'm curious to know how > "substEnv" function works. > I'm trying to use: substEnv varName and it returns the same name. I > tried with $varName, then it gave me error. I'm not sure, what substEnv you mean, so I assume you made a procedure for the stuff previously explained. Now, let's see what happens... substEnv varName you pass in the string "varName", which contains no dollar-chars, so substEnv hasn't got anything to do with it, and returns it unchanged. substEnv $varName before substEnv is called, it's argument is parsed, and the interpreter tries to substitute $varName for the value stored in a variable "varName". As you say, it throws an error, it's possible that you meant "varName" to be an actual environment-variable, and no local variable of that name exists. substEnv {$varName} will pass the literal string (dollar and varName) to the function, and the function will replace it by $env(varName), or perhaps even replace it with the actual environment-var's value. If you post your exact definition of substVar, we can help further, e.g. spot mistakes in substVar that also might cause errors. |