A small beginner-level example of using Expect to feed a script to tclsh
This script reads a Tcl script and enters it into an interactive tclsh.
#! /bin/env tclsh package require Expect proc tclprompt {} { proc [lindex [info level 0] 0] {} { return {\n%\s$} } return {%\s*$} } set timeout -1 set fh [open [lindex $argv 0]] set script [split [read $fh][close $fh] \n] spawn tclsh set command {} foreach line $script { if {[set line [string trimright $line]] eq {}} { continue } else { append command $line\r } if {[info complete $command]} { expect -re [tclprompt] { send $command set command {} } } } expect -re [tclprompt]
Some interesting points:
Setting timeout to -1 allows expect to wait as long as necessary for the next prompt.
[tclprompt] uses a $ to anchor the prompt to the end of the output. Expect is not line-oriented, so this is not foolproof.
[tclprompt] is implemented as a command rather than a variable because the first prompt is not preceded by a newline character, but subsequent prompts are, and manipulating the proc one time is more succinct than putting an extra conditional into the foreach statement.
simply checking for "%" is less robust than checking for a newline followed by "%" followed by space followed by the end of output. It's generally a good idea to be as specific as possible when expecting a prompt.
Here is an event-driven version of the same thing (only tested on *nix):
#! /bin/env tclsh package require Expect proc tclprompt {} { proc [lindex [info level 0] 0] {} { return {\n%\s$} } return {%\s*$} } proc input {fh {command {}}} { #remove the current event handler since leaving it in place seems to interact poorly with [expect] fileevent $fh readable {} if {$command ne {} && [info complete $command]} { expect -re [tclprompt] { send $command } fileevent $fh readable [list input $fh] return } if {[eof $fh]} { set ::done 1 expect -re [tclprompt] { return } } gets $fh line if {[set line [string trimright $line]] ne {}} { append command $line\r } fileevent $fh readable [list input $fh $command] } spawn tclsh set timeout -1 set fh [open [lindex $argv 0]] fconfigure $fh -blocking 0 fileevent $fh readable [list input $fh] vwait done