在while循环内期望-永远循环 [英] expect inside while loop - loops forever

查看:79
本文介绍了在while循环内期望-永远循环的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm new to expect scripts, so please forgive my stumbling...

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

Below is the meat of my expect script. The intent is to scroll thru several screens of output, after each of which the user is prompted with "Continue? [y/n]".

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

Finally, when there are no more screens, a "% " prompt is displayed, which SHOULD cause execution to fall out of the while loop.

    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个"Continue?[y/n]"提示.

What happens instead is... it stays in the while loop forever, sending "y" over and over and over again. I have set "exp_internal 1", and from that output it "seems" like the expect keeps re-reading text that it has already matched on, and so keeps seeing "[y/n]", and keeps sending "y" when, in fact, there are only 2 screens of output, and thus only 2 "Continue? [y/n]" prompts.

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

(The sleep statement is probably not necessary - i just added it to maybe solve the problem - it did NOT - and to allow me to digest the debug output better.)

底线...我的代码中是否有明显的错误?我会提出任何改进建议并消除无止境的循环的建议.

Bottom line... Are there any obvious blunders in my code? I'll take any suggestions at improving this and eliminating the endless looping.

下面的编辑添加到了这个问题.

EDIT BELOW added to this question, after James made a helpful suggestion.

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

Thanks James for your quick response, and your helpful suggestion! But...

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

The same problem persists with your approach (although, yours IS much more elegant, and I'll add this to my expect tool kit.)

正如最初指出的那样,问题肯定是每次执行Expect语句都会重新读取已经读取和比较过的文本.下面是我执行James的"exp_continue"代码并设置"exp_internal 1"以在屏幕上获取调试输出时的输出...

The problem sure seems to be, as noted initially, each execution of the expect statement RE-READS TEXT THAT WAS ALREADY READ AND COMPARED. Below is output when I execute the "exp_continue" code from James, and I set "exp_internal 1" to get debug output on my screen...

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>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]"上匹配期望之后,然后执行期望:持续期望"(上述文本输出的中间),然后接下来读取的文本块是,前几个单词,"SAME TEXT BLOCK"已被阅读和比较.

After the expect matches on "[y/n]" the first time, it then does a "expect: continuing expect" (middle of the above text output), then the block of text it reads next is, except for the first few words, THE SAME TEXT BLOCK IT ALREADY READ AND COMPARED.

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

Am I missing anything??? This has to be a problem if the expect statements re-reads already processed output, yeah? (I have looked at the actual output sent by the target system, and it does NOT send out the same text block a second time.)

同样,我是Expect脚本的新手,但是对于上面的调试输出显示的内容,我看不到任何其他解释. (而且,我很抱歉无法正确格式化输出-我真的在尝试!)

Again, I'm new at expect scripts, but I can't see any other explanation for what the debug output above shows. (And, I apologize for having trouble formatting the output correctly - I really am trying!)

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

Thanxks to anyone who has the patience to read all of the above, and perhaps has an explanation or suggestion.

推荐答案

您需要通过exp_continue命令进行救援. :-)

You need to be rescued by the exp_continue command. :-)

该命令在遇到遇到的情况时会停留在Expect块中,并尝试再次与可能出现的任何新输入进行匹配.

What that command does when encountered is stay within the expect block and try to match again, with whatever new input may come.

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

So you can really shorten your above code to be:

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

让我知道这是否对您有用!

Let me know if that works out for you!

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

EDIT - based on @feenyman99 additional info:

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

Ok, I see what it is. You have the wrong pattern. By using "[y/n]", a match is being produced with a single 'n' character. There's your matched string:

期望:将Expect_out(0,string)设置为"n"

expect: set expect_out(0,string) "n"

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

expect_out(0,string) holds the matched pattern. expect_out(buffer) holds the portion of input removed from the buffer, which holds all input up to and including the matched pattern (from then on, the next expect operation will look for a match on input after the last matched pattern). As you can see, it holds the input up to and including the first literal 'n' character that is found (newlines don't count):

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

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

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

So what is happening is that your script is sending the "y\r" way before the yes/no prompt is presented. And, although I'm not seeing the rest of the logs, I'm guessing the next match happens shortly after, upon hitting the next 'n' character.

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

So you need to change your pattern matching statement to be able to match the yes/no prompt. Better make that a regexp match (-re). I tested the following, and it works (tested on Tcl 8.4.13):

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

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

The multiple backslashes are because the backslash is also an escape character within the pattern matcher. Kind of tricky, but sometimes they are needed.

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

Let me know how that goes. You should be all set now.

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

PS: This may come in handy: http://www.tcl.tk/doc/howto/regexp81.tml

这篇关于在while循环内期望-永远循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆