Expect跳过了一些输出缓冲区,转而使用第一个re模式



我的expect脚本:

#!/usr/bin/expect -f
spawn -noecho zsh -li
expect {
-re {e]d+;[^a]*a} { send_error "escape found: $expect_out(buffer)n"; exp_continue }
"current_dir" { send_error "prompt found: $expect_out(buffer)n" }
timeout { exit 1 }
}

我基本上试图过滤掉转义序列,可能包含"current_dir"字符串,然后匹配该字符串第一次出现在转义序列之外。

运行此命令的错误输出是:

escape found: e];RemoteHost=me@myhost.locala当前目录=/path/to/current_dirashell= 11;shell=zsha逃脱发现:e[1me[7m%e[27me[1me[0m r re]0逃脱发现:e]133RemoteHost=me@myhost.locala当前目录=/path/to/current_dira逃生发现:re[0me[27me] 24me[Je]133;A Aescape found: rne[1;36m/path/to/current_dire[0m on e[1;35mmastere[0m rne[1;32m%e[0m e]133;Ba

所有的escape found"匹配是有效的,除非是最后一个。在第2、第4和第7次匹配中,我们甚至可以看到"current_dir";字符串包含在序列中,这些是我想忽略的。

在最后"escape found"输出时,我们看到在末尾有一个转义序列:"e]133;Ba"。但是有一个&;current_dir&;在没有被普通的"current_dir"匹配之前匹配模式。

我期待看到:

提示符发现:rne[1;36m/path/to/current_dir

代替最后的"escape found"输出。但是,它的时间已经过去了,因为它没有被预料到……(请注意,我试图忽略的转义序列以e]开始,这与e[不同。

我在这里错过了什么?

编辑:注意我正在打印上面的整个expect_out(buffer)。如果我将规则更改为只打印expect_out(0,string),这是每个规则实际匹配的,我将得到:

escape found: e];RemoteHost=me@myhost.locala当前目录=/path/to/current_dirashell= 11;shell=zshae]0;current_dira逃脱发现:e]133RemoteHost=me@myhost.locala当前目录=/path/to/current_dira逃脱发现:e]133;A ABa

所以我希望第二个规则匹配的输出与第一个规则不匹配。

您忽略了规则是按顺序应用的,并且后续匹配发生在最后匹配的规则匹配的点之后。对于您的问题输入缓冲区,两个规则都可以匹配,因此第一个匹配将消耗所有内容直到最后,并掩盖第二个匹配。

您需要以不同的方式编写匹配,以便选择您想要的内容的规则在跳过它的规则之前匹配。然而,这在这里很困难,因为有很多其他的东西在发生;您可能需要更复杂的提示匹配模式,并且需要将放在的前面。

Thismightwork:

expect {
-re {e[1;36m([^e]*)e[0m on e[1;35m([^e]*)e[0m} {
send_error "prompt found: $expect_out(buffer)n"
send_error "prompt dir: $expect_out(1,string)n"
send_error "prompt branch: $expect_out(2,string)n"
}
-re {e]d+;[^a]*a} {
send_error "escape found: $expect_out(buffer)n"
exp_continue
}
timeout {
exit 1
}
}

您可能要考虑在生成之前将TERM环境变量设置为dumb(禁用几乎所有这些转义),这样您就不会有那么多的复杂性来处理。将受控程序的提示符(仅针对会话)显式地设置为易于匹配的内容通常也是一个好主意。这并不是说这一定对你有用,但这些技术通常有助于使匹配问题更容易处理。

对于这个特定的应用程序,您并不真的需要iTerm2转义码,对吗?

作为任何有类似问题的人的参考—主要是如果您希望能够忽略iTerm2转义代码—以下两个脚本中的任何一个都适用于我:

#!/usr/bin/expect -f
spawn -noecho zsh -li
expect {
-re {e]133;Ba} { send_error "prompt found: $expect_out(buffer)n" }
-re {e]d+;[^a]*a} { exp_continue }
"current_dir" { send_error "prompt found: $expect_out(buffer)n" }
timeout { exit 1 }
}

#!/usr/bin/expect -f
spawn -noecho zsh -li
expect {
-re {e]([07]|1337);[^a]*a} { exp_continue }
"current_dir" { send_error "prompt found: $expect_out(buffer)n" }
timeout { exit 1 }
}

感谢@Donald Fellows和@ sexexpect,他们清楚地表明expect以块的形式到达输出缓冲区,因此我们需要小心,对于可能在输出中出现得太近的模式,规则的顺序要正确。

最新更新