String Expect/Tcl:&x27;字符串映射';删除字符串中的内容?

String Expect/Tcl:&x27;字符串映射';删除字符串中的内容?,string,tcl,expect,String,Tcl,Expect,设置:Linux中的Expect/Tcl脚本 用例: 使用期望等待在$user\u命令中使用某些状态的报告 expect -re "notify (.+)\n" set status $expect_out(1,string) send [string map [list SESSION "$status"] "$user_command"] 因此,当应用程序发送“notifyrunning”时,status被设置为

设置:Linux中的Expect/Tcl脚本

用例:

使用
期望
等待在
$user\u命令
中使用某些状态的报告

expect  -re "notify (.+)\n"  
set     status $expect_out(1,string)
send   [string map [list SESSION "$status"] "$user_command"]
因此,当应用程序发送“
notifyrunning
”时,
status
被设置为
running
。 为此,需要将
$user\u命令
中的关键字
STATUS
替换为
$STATUS
,例如

"log STATUS to file"
变成

"log running to file"
为了看看发生了什么,我写道

expect_tty  -re "(.+)\n"  
set         status $expect_out(1,string)
send_user   [string map [list SESSION "$status"] "$user_command"]
当单独运行时,其工作良好。输出是

log someUserInput to file 
键入
someUserInput
以响应
expect\u tty
。但是,作为更大脚本的一部分,字符串映射命令在替换字符串之前删除任何内容,以便输出变为

" to file" 
(没有换行符)我检查了脚本中变量的唯一性,因此这不是问题

问题:


这是怎么回事?如何使脚本健壮?

字符串映射命令完全是确定性的。在其输入字符串的每个字符中,依次考虑映射列表中的任何字符串是否依次匹配,如果是,则执行替换(用成对的字符串),并在替换的子串之后立即考虑字符。(空字符串是一个特例:它从来没有匹配过。)实现它的代码真的很愚蠢,但在现代计算机上恰好是非常缓存友好的,所以它仍然非常快;人们已经尝试了更复杂、据说“更快”的实现,但发现在野外通常遇到的地图类型的实践中速度较慢


如果替换失败,通常是因为输入字符串与您期望的不完全一致。在大多数程序中,这种情况很少见,但在expect程序中更常见,因为其中的终端仿真引擎的输出可以包括元字符,用于移动光标和更改颜色等。(通常最简单的修复方法是告诉生成的程序其终端类型不支持如此复杂的功能,可能是通过将
术语
环境变量设置为
dumb

感谢@glennjackman:

该问题是由于应用程序将换行符报告为
\r\n
,因此中的
(.*)\n

expect_tty  -re "(.+)\n" 
匹配表达式1(括号内的内容)中末尾包含
\r
的内容。当
\r
删除之前的任何内容时,
字符串映射
似乎会在替换的字符串之前剪切任何内容。解决方案是期望排除
\r
,即

expect -re ``(\[^\r\n\]+)``

它收集任何东西,直到行尾,无论格式如何。

尝试提出一个可重现的问题示例。请注意expect始终使用
\r\n
行尾
$status
将在此处包含
running\r
,这将解释意外的输出。@从技术上讲,glenn并不期望“总是使用”
\r\n
s。这是pty通常(并非总是)的行为。Expect本身并不关心从pty得到什么。@glennjackman:请回答这个问题,这样我就可以勾选。