期待内部循环 - 永远循环

时间:2014-01-24 21:14:57

标签: while-loop expect

我是新手,期待脚本,所以请原谅我的绊脚石......

以下是我期望脚本的内容。目的是滚动几个输出屏幕,然后在每个屏幕上提示用户“继续?[y / n]”。

最后,当没有更多屏幕时,会显示一个“%”提示符,该提示符应该导致执行不在while循环中。

    set more_screens 1
    while {$more_screens > 0} {  
        sleep 10
        expect {
            "\[y/n]" { send "y\r"}
            "% "  { set more_screens 0 }
        }
     }

相反的是......它永远停留在while循环中,一遍又一遍地发送“y”。我已经设置了“exp_internal 1”,并且从那个输出“看起来”就像期望一直重新读取它已经匹配的文本,因此不断看到“[y / n]”,并且一直发送“y”事实上,只有2个输出屏幕,因此只有2个“继续?[y / n]”提示。

(睡眠声明可能没有必要 - 我只是添加它可能解决问题 - 它没有 - 并允许我更好地消化调试输出。)

底线......我的代码中是否有明显的错误?我将采取任何改进措施并消除无限循环的建议。

以下编辑在詹姆斯提出有用的建议之后加入了这个问题。

感谢James的快速回复和您的有用建议!但...

同样的问题仍然存在于您的方法中(尽管您的方法更优雅,我会将此添加到我期望的工具包中。)

正如最初提到的那样,问题确实似乎是每个执行期望语句RE-READS TEXT已经阅读和比较。当我从James执行“exp_continue”代码时输出如下,并设置“exp_internal 1”以在我的屏幕上获得调试输出...

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>expect: does "get dump tables\r\n\r% get dump tables\n\r\r\nIfn  TableName           Configured >MaxUse    InUse     LastDropTime\r\n3    cdm_app             100002     190       33        >\r\n3    cdm_conv            2000002    675180    4813      \r\n3    cdm_pdisc           250002     >250002    1304      01-24-2014-19:14:59\r\n3    cdm_kpi             100001     141       25        >\r\n3    cdm_qoe             500003     204918    1578      \r\n3    cdm_qoe_hd          2500003    >582993    1578      \r\n3    cdm_kpi_error_app   100001     5         2         \r\n3    >cdm_kpi_error       100001     7         2         \r\n3    asr_cache           1000000    >1000000   999995    \r\n3    asr_sess            2000000    62670     29748     \r\n3    >asr_conn            3000000    64428     31147     \r\n3    asr_sess_keys       1500000    >1015269   1009049   \r\n3    asr_conn_opts       6000000    0         0         \r\n3    >asr_events          4000000    5239      144       \r\n3    skt_table           2000000    >2000000   2000000   \r\n3    skt_trans           1000000    408020    254674    \r\n3    >ses_sip_db          5000       0         0         \r\n3    ses_gtp_mob_txn     5000       >0         0         \r\nContinue? [y/n]:  " (spawn_id exp6) match glob pattern "[y/n]"? yes
>expect: set expect_out(0,string) "n"
>expect: set expect_out(spawn_id) "exp6"
>expect: set expect_out(buffer) "get dump tables\r\n\r% get dump tables\n\r\r\nIfn"
>send: sending "y\r" to { exp6 }
>expect: continuing expect
>
>
>expect: does "  TableName           Configured MaxUse    InUse     LastDropTime\r\n3    >cdm_app             100002     190       33        \r\n3    cdm_conv            2000002    >675180    4813      \r\n3    cdm_pdisc           250002     250002    1304      01-24-2014->\r\n3    cdm_kpi             100001     141       25        \r\n3    cdm_qoe             500003     >204918    1578      \r\n3    cdm_qoe_hd          2500003    582993    1578      \r\n3    >cdm_kpi_error_app   100001     5         2         \r\n3    cdm_kpi_error       100001     >7         2         \r\n3    asr_cache           1000000    1000000   999995    \r\n3    >asr_sess            2000000    62670     29748     \r\n3    asr_conn            3000000    >64428     31147     \r\n3    asr_sess_keys       1500000    1015269   1009049   \r\n3    >asr_conn_opts       6000000    0         0         \r\n3    asr_events          4000000    >5239      144       \r\n3    skt_table           2000000    2000000   2000000   \r\n3    >skt_trans           1000000    408020    254674    \r\n3    ses_sip_db          5000       >0         0         \r\n3    ses_gtp_mob_txn     5000       0         0         \r\nContinue? 
>[y/n]:  " (spawn_id exp6) match glob pattern "[y/n]"? yes
>expect: set expect_out(0,string) "n"
>expect: set expect_out(spawn_id) "exp6"
>expect: set expect_out(buffer) "  TableName           Con"
>send: sending "y\r" to { exp6 }
>^Csighandler: handling signal(2)
>async event handler: Tcl_Eval(exit 130)

 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

在第一次匹配“[y / n]”之后,它会执行“expect:continue expect”(上面文本输出的中间),然后是下一个读取的文本块,除了前几个单词,相同的文本块已经阅读并比较。

我错过了什么吗?如果期望语句重新读取已处理的输出,这必须是一个问题,是吗? (我查看了目标系统发送的实际输出,并且它不会再次发送相同的文本块。)

同样,我是期待脚本的新手,但我看不出上面的调试输出显示的任何其他解释。 (而且,我为正确格式化输出而道歉 - 我真的在尝试!)

对任何有耐心阅读以上所有内容的人表示赞同,或许有解释或建议。

1 个答案:

答案 0 :(得分:5)

您需要通过exp_continue命令获救。 : - )

遇到的命令会在期望块内停留并尝试再次匹配,无论可能出现什么新输入。

因此,您可以真正缩短上述代码:

expect {
    "\[y/n]" {
        send "y\r"
        exp_continue
    }
    "% " {
        # Do whatever is needed here, after which program flow will continue *outside* of the expect block
    }
}

请告诉我这是否适合您!

编辑 - 基于@ feenyman99附加信息:

好的,我知道它是什么。你有错误的模式。通过使用“[y / n]”,正在生成具有单个“n”字符的匹配。有匹配的字符串:

  

expect:set expect_out(0,string)“n”

expect_out(0,string)保存匹配的模式。 expect_out(缓冲区)保存从缓冲区中删除的输入部分,该部分保存所有输入,包括匹配的模式(从那时起,下一个期望操作将在之后的输入上查找匹配最后匹配的模式)。正如您所看到的,它保存输入,包括找到的第一个文字“n”字符(换行符不计算):

  

expect:set expect_out(buffer)“get dump tables \ r \ n \ r \ n%get dump tables \ n \ r \ n \ r \ nIfn”

所以发生的事情是你的脚本在呈现是/否提示之前发送“y \ r”方式。而且,虽然我没有看到剩下的日志,但我猜测接下来的比赛是在接下来的'n'字符后不久发生的。

因此,您需要更改模式匹配语句,以便能够匹配yes / no提示符。最好使正则表达式匹配(-re)。我测试了以下内容,它可以工作(在Tcl 8.4.13上测试):

expect {
            -re "\\\[y/n]" { send "y\r"}

多个反斜杠是因为反斜杠也是模式匹配器中的转义字符。有点棘手,但有时它们是必需的。

让我知道这是怎么回事。你现在应该全部准备好了。

PS:这可能会派上用场:http://www.tcl.tk/doc/howto/regexp81.tml