簡體   English   中英

使用bash / expect中的變量索引到數組

[英]Indexing into an array using a variable in bash/expect

無法按預期工作的簡單腳本。 我花了數小時的時間進行梳理,試圖發現轉義和引用的正確組合以使其起作用,但我尚未成功。

我有一個K數組,我想從嵌入式的Expect腳本中循環遍歷。

send_user '${list[4]}'

可以按預期工作,在控制台上打印數組的第四個元素。

循環語句:

incr i 1
send_user "\$i"

按預期工作,打印遞增的整數值12345 ...等。

但是,這就是竅門。

send_user "${list[$i]}"

不起作用。 不管$i的值是什么,它總是返回第一個數組元素,我無法遍歷該數組。

是的,我知道用反斜杠將$轉義,以及單引號和雙引號的效果之間的差異等。我已經嘗試了每種組合。 就像我說的,幾個小時。 我要么得到一個錯誤,什么都沒有,要么得到數組的第一個元素(如示例中所示),而不考慮$i的實際值。

我還嘗試將數組作為關聯數組和列表直接移動到期望腳本部分。 娜達 問題不在於讀取數組中的數據,而是使用變量而不是離散數來檢索嵌入式期望代碼中的數組或列表數據。

在放棄這種方法並以另一種方式改寫冗長而復雜的測試工具之前,我想我會吸引眾多的專家。

我在下面嵌入了一個演示測試腳本。

感謝所有的建議。

內森

$ cat test24.sh
list=(zero one two three four)

expect <<- EXPECT_DONE

exp_internal 1

send_user '${list[4]}'

set i 0
send_user "\$i"

send_user "${list[$i]}"
incr i 1
send_user "\$i"
send_user "$list[$i]"
incr i 1
send_user "\$i"
send_user "${list[ "$i" ]}"
incr i 1
send_user "\$i"
send_user ${list[$i]}
incr i 1
send_user "\$i"
send_user "${list[$i]}"
send_user ${list[4]}
send_user "\n"

EXPECT_DONE

echo "Script done."


$ ./test24.sh
'four'0zero1zero2zero3zero4zerofour
Script done.

問題在於,在開始執行Tcl代碼之前,必須對shell數組進行任何擴展,並且您正在嘗試使用Tcl變量對shell數組進行索引。 最好將數組中的值作為參數傳遞給Tcl腳本,而不是使用嵌入的對數組的引用動態生成腳本。 這使您可以單引號here文檔,以避免在腳本內部進行任何其他轉義。

expect -f - "${list[@]}" <<- 'EXPECT_DONE'

exp_internal 1

send_user [lindex argv 4]

set i 0
send_user "$i"

send_user [lindex argv $i]
incr i 1
send_user $i
send_user [lindex argv $i]
incr i 1
send_user $i
send_user [lindex argv $i]
incr i 1
send_user $i
send_user [lindex argv $i]
incr i 1
send_user $i
send_user [lindex argv $i]
send_user [lindex argv 4]
send_user "\n"

EXPECT_DONE

(對Tcl腳本中的任何錯誤表示歉意;距我編寫任何Tcl代碼已有幾十年了。)

您誤解了何時/何地進行擴展。

incr i 1

告訴期望將1加到自己的變量i 但是i從來沒有見過這個shell變量。

類似地:

send_user "${list[$i]}"

在期望看到命令之前由外殼擴展。 外殼程序沒有名為i變量,因此$i擴展為0 (從技術上講沒有擴展0 ,但是當用作列表下標時,它將被視為0),並且${list[0]}變為zero 期望收到:

send_user "zero"

重組代碼的一種可能方法可能是將所有處理移入期望中。 注意'EXPECT_DONE'的單引號,這樣shell不會更改任何輸入:

#!/bin/bash

expect <<- 'EXPECT_DONE'

    set list [list zero one two three four]

    exp_internal 1

    for {set i 0} {$i < [llength $list]} {incr i} {
        send_user "$i"
        send_user [lindex $list $i]
    }

    send_user "\n"

EXPECT_DONE

echo "Script done."

另一個是將所有處理移入bash:

#!/bin/bash

{
    list=(zero one two three four)

    echo "exp_internal 1"

    i=0
    while [[ $i -le ${#list} ]]; do
        echo "send_user \"$i\""
        echo "send_user \"${list[$i]}\""
        : $((i++))
    done

    echo "send_user \"\\n\""

} | expect

echo "Script done."

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM