如何在tcl(expect)脚本中访问bash变量。
我有bash文件说f1.sh,它设置了一些变量,如
export var1=a1
export var2=a2
我需要在我的期望脚本中使用这些变量。
我尝试在我的脚本中使用此功能
system "./f1.sh"
puts "var1 is $::env(var1)"
puts "var2 is $::env(var2)"
但这似乎不起作用。
我看到来自f1.sh的非变量被设置为环境变量。
system "./f1.sh" << # Is this command in my script right ?
我如何从tcl文件中访问这些bash变量。
答案 0 :(得分:1)
我会说这个问题比较笼统。首先,当我想在PoserShell中初始化Microsoft Visual Studio环境(使用.cmd脚本完成)时,我遇到了这个问题。后来我用其他任何组合的脚本语言(Bash,Tcl,Python等)遇到了这个问题。
Hai Vu提供的解决方案很好。如果你从一开始就知道你需要哪些变量,它运作良好。但是,如果您要使用脚本初始化某些环境,我会包含许多变量(您甚至不需要知道这些变量,但是环境的正常运行需要这些变量)。
一般来说,问题的解决方案如下:
我没有现成的解决方案,但我想,类似于此的东西应该有用(注意,下面的代码片段没有经过测试 - 它们的目的只是为了解决方案):
执行脚本; print vars并捕获输出(参数扩展 - {*} - 需要Tcl 8.5,这里我们可以不用它,但我更喜欢使用它):
set bashCommand {bash -c 'myScriptName arg1 arg2 2>&1 >/dev/null && export -p'}
if [catch {*}${bashCommand} output] {
set errMsg "ERROR: Failed to run script."
append errMsg "\n" $output
error $errMsg
}
;# If we get here, output contains the output of "export -p" command
解析命令的输出:
set vars [dict create]
foreach line [split $output "\n"] {
regex -- {^declare -x ([[:alpha:]_]*)=\"(.*)\"$} $line dummy var val
;# 3. Store var-val pair of set env var.
}
存储var-val对或设置env var。这里可以使用几种方法:
3.1。设置Tcl变量并像这样使用它们(取决于上下文):
set $var $val
或
variable $var $val
3.2。设置环境变量(实际上,3.1的子案例):
global ::env
set ::env($var) $val
3.3设置dict或数组并在应用程序(或脚本)中使用它而不修改全局环境:
set myEnv($var) val ;# set array
dict set myEnvDict $var $val ;# set dict
我想再说一遍,这只是收据的想法。更重要的是,由于大多数现代脚本语言都支持正则表达式,因此这个收据可以提供几乎任意一对语言之间的桥梁,但不仅仅是Bash&lt; - &gt; Tcl
答案 1 :(得分:0)
您可以使用here-document,如下所示:
#!/bin/bash
process=ssh
expect <<EOF
spawn $process
...
EOF
答案 2 :(得分:0)
导出的变量只从父进程传递给它的子进程,而不是相反。脚本f1.sh(实际上是运行脚本的bash实例)获取了自己的var1
和var2
副本,如果它们更改它们无关紧要,则退出时更改将丢失。要使变量导出起作用,您需要从bash脚本启动expect脚本。
在f1.sh中,printf您要返回的内容......
printf '%s\n%s\n' "$var1" "$var2"
...并在Tcl中使用exec阅读:
lassign [split [exec ./f1.sh] \n] var1 var2
答案 3 :(得分:0)
也许我看起来不够努力,但我认为没有办法做到这一点。执行bash脚本时,您将创建一个不同的进程。在该过程中发生的事情不会传播回当前过程。
我们可以通过以下方式解决这个问题(感谢potrzebie的想法):
结果是名称和值的交替列表。我们使用此列表为我们的流程设置环境变量。
#!/usr/bin/env tclsh
package require fileutil
# Execute a bash script and extract some environment variables
proc getBashVar {bashScript varsList} {
# Duplicate the bash script to a temp script
set tempScriptName [fileutil::tempfile getBashVar]
file copy -force $bashScript $tempScriptName
# Append a marker to the end of the script. We need this marker to
# identify where in the output to begin extracting the variables.
# After that append the list of specified varibles and their values.
set f [open $tempScriptName a]
set marker "#XXX-MARKER"
puts $f "\necho \\$marker"
foreach var $varsList {
puts $f "echo $var \\\"$$var\\\" "
}
close $f
# Execute the temp script and parse the output
set scriptOutput [exec bash $tempScriptName]
append pattern $marker {\s*(.*)}
regexp $pattern $scriptOutput all vars
# Set the environment
array set ::env $vars
# Finally, delete the temp script to clean up
file delete $tempScriptName
}
# Test
getBashVar f1.sh {var1 var2}
puts "var1 = $::env(var1)"
puts "var2 = $::env(var2)"