在while循环内期望-永远循环

fee*_*n99 3 expect while-loop

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

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

最后,当没有更多屏幕时,将显示“%”提示,这应该导致执行退出while循环。

    set more_screens 1
    while {$more_screens > 0} {  
        sleep 10
        expect {
            "\[y/n]" { send "y\r"}
            "% "  { set more_screens 0 }
        }
     }
Run Code Online (Sandbox Code Playgroud)

相反,发生的事情是……它永远停留在while循环中,一遍又一遍地发送“ y”。我已经设置了“ exp_internal 1”,并且从该输出中输出了“似乎”,就像期望一样继续读取已经匹配的文本,因此一直看到“ [y / n]”,并在出现时继续发送“ y” ,实际上只有2个输出屏幕,因此只有2个“ Continue?[y / n]”提示。

(sleep语句可能不是必需的-我只是添加了它来解决问题-并没有-并允许我更好地消化调试输出。)

底线...我的代码中是否有明显的错误?我会提出任何建议,以改善这一点并消除无休止的循环。

在詹姆斯提出了有益的建议之后,下面的编辑添加到此问题。

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

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

正如最初指出的那样,该问题似乎肯定是每次执行Expect语句都会重新读取已经读取和比较过的文本。当我执行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)

 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Run Code Online (Sandbox Code Playgroud)

在第一次期望值与“ [y / n]”匹配之后,它会执行“期望:持续期望值”(上述文本输出的中间),然后接下来读取的文本块(前几个除外)的话,相同的文本块已被阅读和比较。

我错过了什么吗?如果Expect语句重新读取已经处理过的输出,这将是一个问题,是吗?(我已经查看了目标系统发送的实际输出,并且它没有第二次发送相同的文本块。)

同样,我对期望脚本是陌生的,但是对于上面的调试输出所显示的内容,我看不到任何其他解释。(而且,对于无法正确格式化输出格式,我深感抱歉-我真的在尝试!)

感谢所有有耐心阅读以上所有内容,并且可能有解释或建议的人。

Jam*_*mes 5

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

遇到该命令时,该命令执行的操作将保留在Expect块中,并尝试再次与可能出现的任何新输入进行匹配。

因此,您实际上可以将上述代码缩短为:

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

让我知道是否适合您!

编辑-基于@ feenyman99的其他信息:

好的,我明白了。您的模式错误。通过使用“ [y / n]”,将生成一个带有单个“ n”字符的匹配项。有您匹配的字符串:

期望:设置Expect_out(0,string)“ n”

Expect_out(0,string)保存匹配的模式。Expect_out(buffer)保留从缓冲区中删除的输入部分,该部分保留所有输入,直到并包括匹配的模式(从那时起,下一个Expect操作将在最后一个匹配的模式之后在输入上寻找匹配项)。如您所见,它最多保留输入内容,并包含找到的第一个文字'n'字符(不包括换行符):

期望:设置Expect_out(buffer)“获取转储表\ r \ n \ r%获取转储表\ n \ r \ r \ nIfn”

因此,正在发生的事情是您的脚本在出现“是/否”提示之前发送“ y \ r”方式。而且,尽管我没有看到其余的日志,但我猜想下一个匹配会在击中下一个'n'字符后不久发生。

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

expect {
            -re "\\\[y/n]" { send "y\r"}
Run Code Online (Sandbox Code Playgroud)

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

让我知道怎么回事。您应该已经准备就绪。

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