我如何期望期望脚本中出现换行符?

我如何期望期望脚本中出现换行符?

考虑这个交互式脚本:

#!/usr/bin/env bash
set -eu
while true; do
    read -p '> '
    if [ "$REPLY" == quit ]; then
        break
    fi
    echo "'$REPLY'"
done

现在我想expect与它交互:

#!/usr/bin/env bash
set -eu
echo '
    spawn ./1.sh
    expect >
    send cmd1\n
    expect {\n> }
    send quit\n
' | expect -d

但当我运行它时,它说:

...
expect: does " cmd1\r\n'cmd1'\r\n> " (spawn_id exp6) match glob pattern "\n> "? no
expect: timed out
send: sending "quit\n" to { exp6 }

为什么不匹配?如何检测新提示的出现(完成命令)?

答案1

在语言中,用和expect tcl引用的字符串是有区别的。你可以在两个例子中看到这一点:""{}

$ expect -c 'puts "a\nb"'
a
b
~ $ expect -c 'puts {a\nb}'
a\nb

您的 glob 模式{\n> }由 4 个要匹配的字符组成,但\n不会被特殊解释为转义。如果你使用模式,"\n> "你的匹配应该有效。或者您可以使用 flag-re而不是默认的 glob 模式,并且这两个字符将被正则表达式代码解释为转义符-re {\n> }.

答案2

太长了;博士添加-ex标志。

这里的事情是expect 让事情变得更容易将复杂参数传递给某些命令 ( expect/ interact):

接受包含在单个列表中的参数(期望变体和交互)的命令使用启发式来确定列表实际上是一个参数还是多个参数。仅当列表实际上代表单个参数且该参数具有多个嵌入的 \n 且它们之间有非空白字符时,启发式方法才会失败。这看起来不太可能,但是参数“-nobrace”可用于强制将单个参数作为单个参数处理。可以想象,这可以与机器生成的 Expect 代码一起使用。类似地,-brace 强制将单个参数作为多个模式/操作进行处理。

(来自expect命令的描述)如果整个expect语句的参数需要多于一行,则所有参数可以“支撑”成一行,以避免以反斜杠终止每一行。在这种情况下,尽管有大括号,通常的 Tcl 替换仍然会发生。

我在这里举个例子:

#!/usr/bin/env bash
set -eu
f() {
    echo line 1
    sleep 1
    echo line 2
}
export -f f
echo '
    spawn bash -c f
    expect {
        {line 1} {puts 1}
        {line 2} {puts 2}
    }
    expect \
        {line 1} {puts 1} \
        {line 2} {puts 2}
' | expect

输出:

spawn bash -c f
line 1
1
line 2
2

在我发现的存储库中,启发式在最新的提交(2014 年 5 月)中是如下:如果传递一个参数并且在第一个非空格之前有一个换行符,则该参数被认为是多个参数括成一个。

相关内容