Tcl 反斜杠替换不按我想象的方式工作
Tcl backslash substitution is not working the way I'd imagined
我无法找到一种方法来通过变量将模式(由 autoexpect 创建)作为模式提交给 expect 命令。
我的一个测试脚本的早期版本使用 autoexpect 脚本的手动编辑版本来自动测试应用程序,并且效果很好。不幸的是,它并不是完全可维护的,在应用程序发生变化后,我想我应该将测试分解为一系列交互,自动预期模式存储在一系列 ascii 文件中,然后 运行 一个过程来依次匹配每个片段。典型的片段如下所示(在 vi 中显示时):
run_db\r
\r
\r
\r
为了完整起见,这里是 hexdump 显示的相同片段:
0000000 r u n _ d b \ r \n \ r \n \ r \n \
0000010 r \n
因此,我的片段包含控制字符“\n”和转义序列“\”"r"(如果您明白我的意思!)
我的程序从我的 ascii 文件中读取这个字符串到一个变量中(我使用 "read -nonewline" 来这样做。)
然后我尝试 运行 期望反对模式:
expect {
-gl "$pattern_string" { commands...
}
timeout { commands...
}
}
但是,模式永远不会匹配!更奇怪的是,如果我将字符串本身直接替换为 expect 命令(而不是通过变量),则 expect 会完美匹配,只要我在每个“\r”之后插入一个“\n”:
expect {
-gl "run_db\r\n\r\n\r\n\r\n" { commands...
}
timeout { commands...
}
}
(我一点也不清楚为什么“\n”序列是必需的。它们不在 hexdump 中,所以我认为这 不应该 已匹配!)
我可能误解了替换。就好像我需要用 0x0a 替换“\”"r" 对,然后将变量替换到 expect 命令中。 (可能是在我的 autoexpect 文件的其他地方潜伏着其他转义字符。它相当大。)无论如何,我尝试匹配以下新变量但没有成功:
set substituted_pattern [ subst $pattern_string ]
非常感谢收到任何和所有建议... Allan。
我不太清楚 tcl 在各种情况下对反斜杠的解析,但根据经验,应该用真正的回车-return 替换两个字符 \r
,因为这是您将从 expect
阅读中得到的。你可以这样做:
regsub -all {\r} $pattern_string "\r" pat2
将变量 pat2
设置为新版本。
字符序列 \r
被 glob 匹配器解释为匹配单个文字 r
(反斜杠在这里不是很有用,但在与 glob 元字符一起使用时更有用,例如*
、?
或 [
)。您应该将字符串中的反斜杠加倍(即 \r
)或使用精确匹配(-ex
)。例如:
expect {
-ex "$pattern_string" {
commands...
}
timeout {
commands...
}
}
也可以使用 string map
:
处理字符串以使其与 glob 匹配一起工作
set processed_pattern [string map {{\r} {\r}} $pattern_string]
expect {
-gl "$processed_pattern" {
commands...
}
timeout {
commands...
}
}
我无法找到一种方法来通过变量将模式(由 autoexpect 创建)作为模式提交给 expect 命令。
我的一个测试脚本的早期版本使用 autoexpect 脚本的手动编辑版本来自动测试应用程序,并且效果很好。不幸的是,它并不是完全可维护的,在应用程序发生变化后,我想我应该将测试分解为一系列交互,自动预期模式存储在一系列 ascii 文件中,然后 运行 一个过程来依次匹配每个片段。典型的片段如下所示(在 vi 中显示时):
run_db\r
\r
\r
\r
为了完整起见,这里是 hexdump 显示的相同片段:
0000000 r u n _ d b \ r \n \ r \n \ r \n \
0000010 r \n
因此,我的片段包含控制字符“\n”和转义序列“\”"r"(如果您明白我的意思!)
我的程序从我的 ascii 文件中读取这个字符串到一个变量中(我使用 "read -nonewline" 来这样做。)
然后我尝试 运行 期望反对模式:
expect {
-gl "$pattern_string" { commands...
}
timeout { commands...
}
}
但是,模式永远不会匹配!更奇怪的是,如果我将字符串本身直接替换为 expect 命令(而不是通过变量),则 expect 会完美匹配,只要我在每个“\r”之后插入一个“\n”:
expect {
-gl "run_db\r\n\r\n\r\n\r\n" { commands...
}
timeout { commands...
}
}
(我一点也不清楚为什么“\n”序列是必需的。它们不在 hexdump 中,所以我认为这 不应该 已匹配!)
我可能误解了替换。就好像我需要用 0x0a 替换“\”"r" 对,然后将变量替换到 expect 命令中。 (可能是在我的 autoexpect 文件的其他地方潜伏着其他转义字符。它相当大。)无论如何,我尝试匹配以下新变量但没有成功:
set substituted_pattern [ subst $pattern_string ]
非常感谢收到任何和所有建议... Allan。
我不太清楚 tcl 在各种情况下对反斜杠的解析,但根据经验,应该用真正的回车-return 替换两个字符 \r
,因为这是您将从 expect
阅读中得到的。你可以这样做:
regsub -all {\r} $pattern_string "\r" pat2
将变量 pat2
设置为新版本。
字符序列 \r
被 glob 匹配器解释为匹配单个文字 r
(反斜杠在这里不是很有用,但在与 glob 元字符一起使用时更有用,例如*
、?
或 [
)。您应该将字符串中的反斜杠加倍(即 \r
)或使用精确匹配(-ex
)。例如:
expect {
-ex "$pattern_string" {
commands...
}
timeout {
commands...
}
}
也可以使用 string map
:
set processed_pattern [string map {{\r} {\r}} $pattern_string]
expect {
-gl "$processed_pattern" {
commands...
}
timeout {
commands...
}
}