LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   tcl expect - problem with regular expression in interact mode (https://www.linuxquestions.org/questions/programming-9/tcl-expect-problem-with-regular-expression-in-interact-mode-849003/)

chekhov_neo 12-08-2010 04:23 AM

tcl expect - problem with regular expression in interact mode
 
Hi,

I have something like the following in my expect script:

Code:

interact {
    -nobuffer -re {^s\r} {
        send_user "\nExiting\n"
        exit
}

I have put the "^" anchor to match only those pattern that does not have anything before "s"

e.g.

1.when I type "s" followed by "enter" key it should match.

2.if I type something like "chess" followed by "enter" key it shouldn't match.

Unfortunately, the second case is also being matched by the regular expression I have in my code.

Please help!

crts 12-08-2010 08:47 AM

I do not see the problem ...
 
Hi,

I created these two little scripts to verify your observation. However, it seems to work as expected:
exp.scr
Code:

#!/usr/bin/expect -f

spawn ./sh.scr
expect -exact "init: "
send "s\r"
interact {
        -nobuffer -re {^s\r} {
        send_user "\nExiting\n"
        exit
        }
}

exit

sh.scr
Code:

#!/bin/bash

echo "init: "
read ans
echo "your initial response is: '$initans'"

echo "type somthing: "
read ans
if [[ $ans = "s" ]];then
        echo "you typed '$ans' and this part of the program should NOT execute!"
else
        echo "you typed '$ans' instead of 's' and you should see this message."
fi

I used an initial 'send' to make sure that the problem is not the result of a previously entered 's\r' which still resides in the buffer.
Here is the output I get:
Code:

$ ./exp.scr
spawn ./sh.scr
init:
s
your initial response is: ''
type somthing:
s
Exiting
$

The program exits correctly. And when I enter 'chess':
Code:

$ ./exp.scr
spawn ./sh.scr
init:
s
your initial response is: ''
type somthing:
chess
you typed 'chess' instead of 's' and you should see this message.
$

The program does not exit, which is also the correct behaviour.

I assume that the missing second closing '}' is just a typo in your post. Otherwise, you might want to correct it.
If have misunderstood your requirement then maybe you should post some real input/output of your program and what you actually expected.

chekhov_neo 12-09-2010 01:27 AM

code output
 
Hi crts,

Thank you very much for your time. For me the problem occurred when I entered "chesss" and not "chess". I apologize for my mistake. And the missing "}" is a typo. I executed my code again but now with debugging info.

My code:

Code:

#!/usr/bin/expect -d

spawn bash
expect "#"
interact {
    -nobuffer -re {^s\r} {
        send_user "\nExiting\n"
        exit
        }
}

and I got the following output:

Code:

host1:~# ./test
expect version 5.43.0
argv[0] = /usr/bin/expect  argv[1] = -d  argv[2] = ./test
set argc 0
set argv0 "./test"
set argv ""
executing commands from command file ./test
spawn bash
parent: waiting for sync byte
parent: telling child to go ahead
parent: now unsynchronized from child
spawn: returns {6472}

expect: does "" (spawn_id exp6) match glob pattern "#"? no
host1:~#
expect: does "host1:~# " (spawn_id exp6) match glob pattern "#"? yes
expect: set expect_out(0,string) "#"
expect: set expect_out(spawn_id) "exp6"
expect: set expect_out(buffer) "host1:~#"
defining key ^s\r, action \n        send_user "\nExiting\n"\n        exit\n
tty_raw_noecho: was raw = 0  echo = 1
spawn id exp0 sent <c>
spawn id exp6 sent <c>
cspawn id exp0 sent <h>
spawn id exp6 sent <h>
hspawn id exp0 sent <e>
spawn id exp6 sent <e>
espawn id exp0 sent <s>
spawn id exp6 sent <s>
sspawn id exp0 sent <s>
spawn id exp6 sent <s>
sspawn id exp0 sent <\r>
spawn id exp6 sent <\r\n>

spawn id exp6 sent <bash: chess: command not found\r\n>
bash: chess: command not found
spawn id exp6 sent <host1:~# >
host1:~# spawn id exp0 sent <c>
spawn id exp6 sent <c>
cspawn id exp0 sent <h>
spawn id exp6 sent <h>
hspawn id exp0 sent <e>
spawn id exp6 sent <e>
espawn id exp0 sent <s>
spawn id exp6 sent <s>
sspawn id exp0 sent <s>
spawn id exp6 sent <s>
sspawn id exp0 sent <s>
spawn id exp6 sent <s>
sspawn id exp0 sent <\r>
interact: set interact_out(0,string) "s\r"

Exiting
tty_set: raw = 5, echo = 0
host1:~#

So when I entered "chesss" the pattern matched and it exited. I'm wondering how did it match.

crts 12-09-2010 02:55 PM

Firstly, it is important to understand that the characters '^' and '$' anchor the beginning and end of received data. They do NOT anchor the beginning and end of a line.

To understand the observed behavior let's assume there is a "RegExBuffer" for the incoming data. Since you have defined two characters in your RegEx this buffer will hold up to two bytes. This buffer will be emptied as soon as it does not match the RegEx. Let's have a closer look at what happens when you type chess:
Our RegEx is "s\r".
'c' is typed
Code:

RegExBuffer        [c][] --> RegEx is mismatched and the buffer is emptied

-> RegExBuffer        [][]

The above procedure is repeated for the characters 'h' and 'e'.
Now the first 's' is typed
Code:

RegExBuffer        [s][] --> RegEx is starting to match; the buffer is not emptied

-> RegExBuffer        [s][]

Now the second 's' is typed
Code:

RegExBuffer        [s][s] --> RegEx is mismatched and the buffer is emptied

-> RegExBuffer        [][]

If you hit 'return' at this point then the buffer would look like
Code:

RegExBuffer        [\r][] --> RegEx is mismatched and the buffer is emptied

-> RegExBuffer        [][]

If you do NOT hit 'return' after the second 's', but misspell chesss and type in a third 's' then this is how RegExBuffer looks like
Code:

RegExBuffer        [s][] --> RegEx is starting to match again; the buffer is not emptied

-> RegExBuffer        [s][]

If you hit 'return' after the third 's' then
Code:

RegExBuffer        [s][\r] --> This is a perfect match! The 'Exiting' branch is executed!
From this example it is hopefully clear that any odd number of consecutive 's' will match the RegEx, i.e. ches, chesss and also chesssss (that's 5 s) will trigger the 'Exiting' branch.
To further verify the mechanism I described above you can change your RegEx to "ss\r". Now the RegEx buffer will hold up to 3 characters. Hence, the 'Exiting' branch will be executed whenever you enter 2,5,8 ... consecutive 's'.
I am quite confident that there is a workaround for this problem; although not sure how it will look. It would be nice if you could post the solution here once you have it.


All times are GMT -5. The time now is 01:58 PM.