2

In TCL Expect do I need to escape the $ to use it as an anchor? For example to match t if it occurs in last position should be:

expect t$

But this does not work, I suspect because TCL is interpreting the $. I tried all of the following without success

expect -re {t$}
expect t\$
expect t\\$

... but no luck. Help

While I'm at it, how do you match any response, and capture the whole response, i.e. I suspect something like the following

expect ^*$

but my $ is broken.

Alan Moore
  • 73,866
  • 12
  • 100
  • 156
wat
  • 53
  • 1
  • 4
  • Tcl shouldn't have interpolated the `$` in the curly braces. I suspect something else is the case, here. Also, you probably mean `expect "^.*$"`, but you actually don't even need the anchors in that case: `expect ".*"` is sufficient. Hm, I do recall reading something about "expect indigestion". I _think_ `$` may match the end of the buffer, not the end of the line, in this case. Try `.*\n$` to see. – Andrew Cheong Jan 13 '13 at 02:31
  • 1
    both `expect t$` and `expect {t$}` should work. Try adding `exp_internal 1` to the beginning of your script -- then expect will show you why it's not matching. – glenn jackman Jan 13 '13 at 04:06
  • thanks acheong and glenn, adding exp_internal showed that i had to add the \n to the regex, so to match a t in last position i useed: expect -re {t\n$} and it works, whereas expect -re {t$} does nothing since every response has the newline in last position. and to match any response and capture the whole responsre is expect -re {\n$} – wat Jan 13 '13 at 04:43

2 Answers2

0

As pointed out by acheong87 the expect script includes the newline character in the responses. To see this use glen jackman tip and add exp_internal 1 to the top of the script. So to match the character "t" if it is in last position is:

expect -re {t\n$} 

and one way to capture any response and the whole response is

expect -re {^.*.\n$}
wat
  • 53
  • 1
  • 4
0

You don't have to in most cases, but read on. Expect is basically a TCL shell with a few extensions. TCL uses the dollar sign ($) to carry out variable substitution if and only if it is found in one of the 3 contexts described in the TCL dodekalogue (http://wiki.tcl.tk/10259). In short, they are the $name, the ${name} and the $name(name) forms. When the TCL interpreter processes your script, it will not substitute the dollar sign, but leave it there in its literal form if the above conditions are not met, which is the case in e.g.

expect "abc\r\n$"

Unless you are using the brace syntax, you cannot use anything starting with or containing a double quote as a variable name. It is wise however to escape the dollar sign via a backslash anyway.
I want to note that in my old version of Expect (5.25.0), the regexp processor doesn't carry out backslash-escape substitutions, so if you are using such a version, you cannot use braces to escape the newline character. After Expect(TCL) is done with substitution and the regular expression matching starts, there has to be a literal newline character which is achieved by letting Expect do the substitution of \n.

Since Expect's regular expressions are not line-oriented but buffer-oriented, ^ and $ mean start of buffer and end of buffer, respectively.
Dependent on the buffering mode of your terminal, Expect probably only gets the output of the spawned process line-by-line (like in my, and most cases), albeit without the newline character.
This guarantees (EDIT: not really guaranteed, see the end) that the current end of buffer always coincides with the end of a line in the output of a spawned process.
Another issue is that (at least my UNIX version) of Expect does not match the newline character with \n, instead only with \r\n !
I.e. it seemingly puts these two characters at the end of every chunk of input it fetches (EDIT: actually, replaces the normal newline).

So to match the character 't' at the end of the buffer, first you have to make sure that there is a terminating newline after the 't' and the spawned process is waiting or otherwise guarantees that Expect's buffer does not get filled with more input.
On the part of Expect, the proper command would be:

expect -re "t\r\n\$" {...}

Note that the backslash before the dollar sign was not really necessary, I only put it there to support the good habit of doing so.

EDIT: Of course, the newline does get passed to Expect contrary to what I first wrote, which it seemingly substitutes with "\r\n".
I also wanted to add that there is a case I know of in which the buffer of the spawned process gets flushed, namely when the process terminates. Thus it is not actually guaranteed that the end of a new line is the current end of the buffer, but it is so in most cases.
If you try waiting for a pattern from a program that ends earlier than the Expect script, you will get the pattern, without any newline character at the end!
In this case you can match the bare character 't' at the end of the text simply with

expect -re "t$" {...}
Community
  • 1
  • 1
Larry
  • 427
  • 2
  • 10