2013-07-26 297 views
2

如何在tcl(expect)腳本中訪問bash變量。如何在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變量。

回答

1

我要說的是,這個問題是相當普遍的。首先我遇到了這個問題,當時我想在PoserShell中初始化Microsoft Visual Studio環境(這是使用.cmd腳本完成的)。後來我遇到了其他腳本語言的任何組合(Bash,Tcl,Python等)的問題。

Hai Vu提供的解決方案很好。如果你從一開始就知道你需要哪些變量,那麼效果很好。但是,如果您要使用腳本來初始化某些環境,那麼我包含數十個變量(您甚至不需要知道這些變量,但是這些變量是正常操作環境所需的)。

一般情況下,該問題的解決方案如下:

  1. 執行腳本,並在年底全部打印環境變量和捕獲輸出。
  2. 匹配模式的輸出行,如「變量=值」,其中是你想得到的。
  3. 使用您的語言設施設置環境變量。

我沒有現成的解決方案,但我想,類似這種東西應該工作(注意,該片段以下未測試 - 他們只是旨在給予解決的想法):

  1. 執行腳本;打印VAR和捕獲輸出(參數擴展 - {*} - 需要的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 
    
  2. 解析命令的輸出:

    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. 
    } 
    
  3. Store var-val pair或set env var。這裏可以使用幾種方法:

3.1。設置Tcl變量中,並使用它們像這樣的(根據上下文):

set $var $val 

variable $var $val 

3.2。設置環境變量(實際上,3.1分的情況下):

global ::env 
set ::env($var) $val 

3.3集字典或數組並沒有全球環境的改變您的應用程序(或腳本)中使用它:

set myEnv($var) val   ;# set array 
dict set myEnvDict $var $val ;# set dict 

我我想重申,這只是收據的想法。更重要的是,由於大多數現代腳本語言都支持正則表達式,因此該收據可以提供幾乎任意一對語言之間的橋樑,但不僅僅是Bash < - > Tcl

+0

感謝Hai Vu&Dmitry – user2622965

0

可以使用here-document,像這樣:

#!/bin/bash 
process=ssh 
expect <<EOF 
    spawn $process 
    ... 
EOF 
0

導出的變量只能從父進程傳遞給它的孩子,而不是周圍的其他方式。腳本f1.sh(實際上是運行腳本的bash實例)獲取它自己的var1var2的副本,並且它是否更改它們並不重要,更改在退出時會丟失。爲了讓變量導出工作,您需要從bash腳本啓動expect腳本。

在f1.sh,printf你想回到什麼......

printf '%s\n%s\n' "$var1" "$var2" 

...和Tcl的與exec閱讀:

lassign [split [exec ./f1.sh] \n] var1 var2 
0

可能是我沒有看夠硬,但我沒有看到任何方式來做到這一點。當你執行bash腳本時,你創建了一個不同的進程。該過程中發生的事情不會傳播回當前流程。

我們可以工作,解決此問題通過執行以下(感謝potrzebie的想法):

  1. 在複製的bash腳本到一個臨時腳本
  2. 追加到temp一些腳本命令結束以回顯標記,以及變量列表和它們的值
  3. 執行臨時腳本並解析輸出
  4. 結果是交替名稱和值的列表。我們使用這個列表爲我們的過程設置環境變量。

    #!/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)"