【问题标题】:expect inside while loop - loops forever期待在while循环中 - 永远循环
【发布时间】:2014-01-24 21:14:57
【问题描述】:

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

以下是我的期望脚本的内容。目的是滚动通过几个输出屏幕,在每个屏幕之后都会提示用户“继续?[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]”提示。

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

底线...我的代码中是否有任何明显的错误?我会采纳任何建议来改进这一点并消除无休止的循环。

在 James 提出有用的建议后,在此问题中添加了 EDIT BELOW。

感谢 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)

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

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

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

再说一次,我是 expect 脚本的新手,但是对于上面的调试输出显示的内容,我看不到任何其他解释。 (而且,我很抱歉无法正确格式化输出 - 我真的在努力!)

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

【问题讨论】:

    标签: while-loop expect


    【解决方案1】:

    你需要被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”字符生成匹配项。有你匹配的字符串:

    期望:设置期望输出(0,字符串)“n”

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

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

    所以发生的情况是您的脚本在出现是/否提示之前发送“y\r”方式。而且,虽然我没有看到其余的日志,但我猜下一场比赛会在不久之后发生,在击中下一个 'n' 字符时。

    因此,您需要更改模式匹配语句以匹配是/否提示。最好让它成为一个正则表达式匹配(-re)。我测试了以下内容,它可以工作(在 Tcl 8.4.13 上测试):

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

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

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

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

    【讨论】:

      猜你喜欢
      • 2014-05-30
      • 2021-11-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-20
      • 1970-01-01
      • 2016-04-10
      • 1970-01-01
      相关资源
      最近更新 更多