SETUP: Expect/Tcl Script in Linux
USE CASE:
Using expect
to wait for the report of some status to be used in a $user_command
.
expect -re "notify (.+)\n"
set status $expect_out(1,string)
send [string map [list SESSION "$status"] "$user_command"]
So when the application sends "notify running
", then status
is set to running
.
For that a keyword STATUS
in $user_command
needs to be replaced with $status
, such that, for example
"log STATUS to file"
becomes
"log running to file"
To see what is happing, I wrote
expect_tty -re "(.+)\n"
set status $expect_out(1,string)
send_user [string map [list SESSION "$status"] "$user_command"]
which works fine when running isolatedly. The output is
log someUserInput to file
when typing someUserInput
to responde to expect_tty
. However, as part of a larger script, the string map command it removes anything before the string replacement, so that the output becomes
" to file"
(without a newline) I checked for the uniqueness of variables in the script, so that this is not an issue.
QUESTION:
What is going on here? How can I make the script robust?
Thanks to @glennjackman:
The problem is due to applications reporting newline as \r\n
, so that (.*)\n
in
expect_tty -re "(.+)\n"
matches in expression 1 (the thing inside the brackets) something that includes \r
at the end. With \r
removing anything before it, string map
seems to cut anything before the replaced string. The solution is to expect something that excludes \r
, i.e.
expect -re ``(\[^\r\n\]+)``
which collects anything until end of line, whatsoever the format may be.