Saturday, October 11, 2008

Capturing output of Expect [send] command

В кои то веки посреди груд папуасского мусора в зиване возник производственный вопрос. Соколов, конечно, умудрился максимально напустить тумана в том, что конкретно ему хотелось от Expect, хотя с поднятой им проблемой сталкиваются практически все новички в Expect, так что мы позволим себе здесь вышеприведенное обсуждение продолжить.

Правильно сформулированный вопрос стоит так: я посылаю с [send] текст и желаю получить ответ не просто поймав его посредством [expect], но желаю иметь этот output в переменной для моей-не-скажу-для-чего прихоти.

Короткий ответ на такой вопрос будет такой: см. на переменную expect_out, которую заполняет [expect]. Это обычный Tcl array. Лучше всего понять, как он заполняется, это написать

flush stdout
parray expect_out

Где нибудь в конце вашего диалога со spawn'еной программой. Для окончательно ясности, напишем 2 скрипта: 1-й на sh, который будет программкой с которой будет работать 2-й скрипт, написанный на Expect.

% cat foobar.sh
#!/bin/sh

printf "Please enter your name: "
read name

[ -z "$name" ] && {
  echo "For what such secretiveness?"
  exit 1
}

echo -- Thank you, $name

Все что сделает наш второй Expect-скрипт, -- это избавит вас от утомительной работы по введению имени, которое потребует foobar.sh.

% cat foobar-expect.tcl
#!/bin/sh
# -*-tcl-*- \
# the next line restarts using expect \
exec expect "$0" "$@"

set cmd ./foobar.sh
set timeout 5
if {[catch {
  spawn -noecho $cmd
} r]} {
  puts stderr "$argv0 error: $r"
  exit 1
}

log_file -noappend temp-file
expect "Please enter your name: "
set name "Jeeves"
#set name ""
exp_send "$name\n"
expect {
  -re "Thank.* ${name}\r\n$" { puts "-- Yes, sir." }
  timeout {
      send_user "timeout because there was no prompt\n"
      exit 1
  }
}

flush stdout
parray expect_out

set status [wait $spawn_id]
if {[lindex $status 2] == 0} {
  exit [lindex $status 3]
}

Теперь запустим foobar-expect.tcl, чтобы окончательно разобраться с expect_out:

% ./foobar-expect.tcl
Please enter your name: Jeeves
-- Thank you, Jeeves
-- Yes, sir.
expect_out(0,string) = Thank you, Jeeves

expect_out(buffer)   = Jeeves
-- Thank you, Jeeves

expect_out(spawn_id) = exp4

$expect_out(0,string) содержит именно то, что мы поймали командой [expect] после [exp_send]. Чтобы посмотреть на полный диалог, загляните в появившийся файл temp-file, создаваемый командой [log_file].

No comments:

Post a Comment