Как l oop Bash массив в сценарии Expect - PullRequest
0 голосов
/ 09 января 2020

У меня есть массив в моем скрипте bash:

my_file=("a.txt" "b.txt" "c.txt" "d.txt" "e.txt")

Теперь в том же файле я хочу использовать Expect и сделать цикл для получения некоторых файлов в sftp. Это мой код

/usr/bin/expect <<EOF
set timeout -1
array set param ${!my_file[@]}
spawn sftp $sftp_option $user@$host
expect "Password:"
send "$pswd\r"
expect "sftp>"
for arg in $param; do
send "mget $arg*\r"
expect "sftp>"
done
send "bye\r"
EOF

С этим кодом я не могу сделать al oop с этим массивом выше. И я получил ошибку, подобную этой:

Неправильно # args: должно быть "список массивов arrayName list" при выполнении "набор параметров массива 0 1"

Полный Код:

#!/bin/bash

export PATH=$PATH:/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/root/bin;

homeDir=/home/jlo_apps/daemon/jlo_ex/collection/wssh;
filePID=$homeDir/rsync_rfs_bbni.pid;

trap "rm $filePID; exit" SIGHUP SIGINT SIGTERM;

if [ -e $filePID ]; then
    datenow=`date`; 
    echo "[ Rsync ] There are rsync processes still running...";
    echo "========================= $datenow =========================";
    exit 1;
else
    echo $$ > $filePID;
fi

. $homeDir/get_rfs_bni.conf;

strconn="$dbuser/$dbpass@$dbhost:$dbport/$dbsid";

profile=`$sqlldr_path -s $strconn <<< "select host|| '|' ||username|| '|' ||password|| '|' ||port|| '|' ||outdir from p_epdp where bank='BBNI';" | tail -2 | head -1`;
mapfile mid < <($sqlldr_path -s $strconn <<< "select distinct(substr(mid, 0, 13)) from p_mid where kode_bank = 'BBNI';" | tail -3 | head -2);

host=$(echo $profile | cut -d"|" -f1);
user=$(echo $profile | cut -d"|" -f2);
pswd=$(echo $profile | cut -d"|" -f3);
port=$(echo $profile | cut -d"|" -f4);
outdir=$(echo $profile | cut -d"|" -f5);

/usr/bin/expect <<EOF
set timeout -1

spawn sftp $sftp_option $user@$host
expect "Password:"
send "$pswd\r"
expect "sftp>"
send "cd $outdir\r"
expect "sftp>"
send "lcd $rfshome\r"
expect "sftp>"
foreach arg {${mid[@]}} {
 send "mget $arg*\r"
 expect "sftp>"
}
send "bye\r"
EOF

rm $filePID;

sleep 10;

datenow=`date`; 
echo "========================= $datenow =========================";

Есть ли какое-либо решение этой проблемы без отдельного файла между bash и Expect?

Ответы [ 2 ]

2 голосов
/ 09 января 2020

Правильный синтаксис для интерполяции значений массива будет

array set param ${my_file[@]}

без !, но при этом получается

array set param a.txt b.txt c.txt d.txt e.txt

Однако синтаксис Expect для создания массивов выглядит как

array set param {one one.txt two two.txt}

с чередующимися ключами и значениями (больше похоже на ассоциативный массив, чем просто список значений). Но тогда вы все равно не можете использовать оболочку for l oop внутри сценария Expect; язык использует совершенно другой синтаксис (Expect основан на TCL, а не на скрипте оболочки).

Возможно, вы ищете что-то вроде

/usr/bin/expect <<EOF
set timeout -1
spawn sftp $sftp_option $user@$host
expect "Password:"
send "$pswd\r"
expect "sftp>"
foreach arg {${my_file[@]}} {
 send "mget $arg*\r"
 expect "sftp>"
}
send "bye\r"
EOF

, где я набрал правильный TCL l oop Синтаксис из Передать bash массив для ожидания сценария

0 голосов
/ 09 января 2020

Это немного неловко, но вы можете сделать это:

$ my_file=("a.txt" "b.txt" "c.txt" "d.txt" "e.txt")

$ expect -f - -- "${my_file[@]}" <<'END'
foreach arg $argv {puts $arg}
END
a.txt
b.txt
c.txt
d.txt
e.txt

-f - указывает на ожидаемое использование stdin для файла сценария.
Затем -- завершает параметры командной строки и оставшиеся аргументы go в список argv.

Не забудьте использовать процитированный heredo c, как я продемонстрировал. В противном случае оболочка расширит ожидаемые переменные.

...