# cat expect_test
#!/usr/bin/expect
spawn ./test
expect {
"xxx" { }
"123" { puts "got123"; exp_continue; }
"555" { puts "got555"; exp_continue; }
}
# cat test
#!/bin/bash
sleep 3
echo "444"
sleep 3
echo "555"
sleep 3
echo "123"
sleep 3
echo "666"
sleep 3
echo "123"
test脚本用于输出一组数据:
444
555
123
666
123
expect_test脚本匹配test脚本的输出,实际的匹配结果是:
# ./expect_test
spawn ./test
444
555
got555
123
got123
666
123
got123
如果我们把test脚本中的sleep 3删除,那么此时的匹配结果是:
# ./expect_test
spawn ./test
444
555
123
666
got123
123
got123
此时我们发现在没有sleep 3的情况下,555没有匹配上,这是为什么呢?
因为我理解expect的匹配机制是:
expect语言在匹配的时候,按顺序取出expect语句中指定的匹配字符串,然后在缓冲区中搜索它。
先取出第一个字符串在缓冲区中查找它,如果找到了:
在没有exp_continue的情况下,就结束这次匹配了;
在exp_continue存在的情况下,会在后续的缓冲区中(匹配到的那一行以及以上的缓冲区作废)继续重新开始新一轮的匹配。
如果没找到,那么取出下一个字符串继续匹配。
在sleep 3存在的情况下能匹配上555是因为,test每间隔3秒输出一个数据,
每输出一个数据后,都会匹配一轮,
1.test输出444之后,
先在444中找xxx,没命中
然后找123,没命中
然后找555,没命中
2.test输出555之后,
先在555中找xxx,没命中
然后找123,没命中
然后找555,命中,因为exp_continue的存在,expect不会退出,而是继续重新开始匹配。如果没有exp_continue脚本就结束了。
3.test输出123之后,
先在123中找xxx,
然后找123,命中并继续重新匹配
然后找555,没命中
4.依此类推。。
但是当删除sleep 3之后,test一股脑儿输出了所有数字,就是把所有数字都写到了expect_test的缓冲区中。
本例子中,expect先拿出xxx在缓冲区中去搜索它,没命中。
然后拿出123在缓冲区中搜索它,命中了第一行的123,此时因为有exp_continue的存在,在输出got123之后,又重新开始匹配(从xxx开始),
此时搜索缓冲区的时候,是从第一个123以后的内容开始搜索的,因为命中的内容以及以前的内容就不会再继续去匹配了,
所以此时会名中第二个123,然后,在输出got123之后,又重新开始匹配(从xxx开始)。
这时候,因为是从命中的第二个123以后的内容开始搜索555的,所以会匹配失败,因为123以前的555已经失效不会去匹配,而123以后没有555。
这就是为什么555没有匹配上的原因。