Bash & TCL: не получается одинаковый вывод из одной и той же функции - PullRequest
0 голосов
/ 20 декабря 2018

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

#!/bin/bash

ReturnElementFromId() {
    local ix="$1" ; shift
    local arr=("$@")

    echo "${arr[$ix]}"
}

export -f ReturnElementFromId
ARRAY=("This is" "a" "test array !")

echo ">> $(ReturnElementFromId 2 "${ARRAY[@]}")"

expect -c "
    set output $(ReturnElementFromId 2 \"${ARRAY[@]}\")
    puts \">> \$output\"
"

Когда дело доходит до печати вывода, я получаю другой вывод из "той же команды".Вот как это выглядит:

>> test array !
>> a

Я не понимаю, почему выходные данные двух одинаковых команд не одинаковы.Может ли кто-нибудь помочь мне?

С уважением

Ответы [ 2 ]

0 голосов
/ 22 декабря 2018

Передача ожидаемых данных из оболочки лучше выполнять через среду, в противном случае вы попадете в кавычки:

#!/bin/bash
...

export __element=$(ReturnElementFromId 2 "${ARRAY[@]}")

expect <<'END_EXPECT'
   set element $env(__element)
   puts ">> $element"
END_EXPECT

Использование , указанного здесь - doc означает, что выне нужно экранировать что-либо (не кавычки, не переменные) в ожидаемом коде из оболочки.

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

0 голосов
/ 20 декабря 2018

Частичный ответ, чтобы пролить свет на эту проблему

Первый индекс массива Bash равен 0. Поэтому, если ваши индексы массива равны 0 => "This is", 1 => "a"2 => "test array !".Следовательно, ваш первый вызов bash развертывается следующим образом:

++ ReturnElementFromId 2 'This is' a 'test array !'
++ local ix=2
++ shift
++ arr=("$@")
++ local arr
++ echo 'test array !'
+ echo 'test array !'
>> test array !

Следовательно, чтобы ваш первый вызов вернул желаемый результат, вам нужно уменьшить значение ix на 1.

Ваш второй вызов ReturnElementFromId, с другой стороны, развертывается по-другому, и ваш массив не передается функции, как вы ожидали.Обратите внимание, что ваш массив разделен на части и обработан таким образом, что каждое слово было отдельным индексом от вашего массива (попробуйте вызвать другие индексы, чтобы проверить это).

++ ReturnElementFromId 2 '"This' is a test array '!"'
++ local ix=2
++ shift
++ arr=("$@")
++ local arr
++ echo a
+ expect -c '
    set output a
    puts ">> $output"
'
>> a

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

Редактировать: Распаковать переменную

В Bash есть различные типы кавычек, которые говорят, как переменные и специальные / метасимволы должныбыть интерпретированным [ 1 ].Двойные кавычки (") называются слабыми кавычками , поскольку они допускают раскрытие переменных.Учитывая ваш вопрос, сделайте два следующих вызова, чтобы понять, как bash интерпретирует ваши вызовы функций:

call-A$ echo ">> $(ReturnElementFromId 2 "${ARRAY[@]}")"
call-B$ echo ">> $(ReturnElementFromId 2 ${ARRAY[@]})"

call-A был предоставлен вами и оставляет массив вне цитаты, а call-B оставляет его внутрицитата (то есть между двумя ").В call-A, поскольку массив находится вне двойных кавычек, bash не расширяет свое значение перед вызовом ReturnElementFromId, сохраняя, таким образом, предполагаемую структуру.С другой стороны, call-B расширяет ваш массив перед вызовом ReturnElementFromId, следовательно, разбирает ваш массив на кусочки.Ниже вы можете видеть, что в call-A ваш вызов функции группирует слова в одинарных кавычках, в то время как call-B расширил массив (до вызова) и «отправляет» каждый символ «отдельно».Ниже приведены результаты обоих вызовов:

call-A: ++ ReturnElementFromId 2 'This is' a 'test array !'
>> test array !
call-B: ++ ReturnElementFromId 2 This is a test array '!'
>> a

Даже если они не совпадают, расширение call-B напрямую относится к вашему расширению expect.Поскольку expect использует двойные кавычки, bash расширяет вашу переменную и разбирает ваш массив.

...