Индексирование в массив с использованием переменной в bash / Ожидается - PullRequest
0 голосов
/ 17 февраля 2019

Простой скрипт, который не работает должным образом.Я потратил много времени, пытаясь найти правильную комбинацию экранирования и цитирования, чтобы заставить его работать, но я пока не добился успеха.

У меня есть массив в K, который я хочу перебрать из встроенного сценария ожидания.

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.

Ответы [ 2 ]

0 голосов
/ 17 февраля 2019

Вы неправильно понимаете, когда и где происходит расширение.

incr i 1

говорит, что вы ожидаете добавить 1 к своей собственной переменной i.Однако переменная оболочки i никогда этого не видит.

Аналогично: оболочка

send_user "${list[$i]}"

раскрывается до того, как ожидаемая команда увидит команду.В оболочке нет переменной с именем i, поэтому $i расширяется до 0 (технически в ничто, но при использовании в качестве нижнего индекса списка она будет обрабатываться как 0), а ${list[0]} становится zero.Expect получает:

send_user "zero"

Одним из возможных способов реструктуризации вашего кода может быть перемещение всей обработки в ожидаемое.Обратите внимание на одинарную кавычку 'EXPECT_DONE', чтобы оболочка не меняла входные данные:

#!/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."
0 голосов
/ 17 февраля 2019

Проблема заключается в том, что любые расширения массива shell должны произойти до того, как код Tcl начнет выполняться, а вы пытаетесь проиндексировать массив shell с помощью переменной Tcl.Лучше передавать значения в массиве как arguments в сценарий Tcl, а не динамически генерировать сценарий со встроенными ссылками на массив.Это позволяет вам заключить в кавычки здесь документ, чтобы избежать дополнительного экранирования внутри скрипта.

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.)

...