首页 > 解决方案 > 期望:^ 在描述不同 Cisco 设备的命令提示符的正则表达式中不起作用

问题描述

我目前正在优化一个期望脚本以从不同类型的 Cisco 设备收集信息,并且在正则表达式领域存在问题。非常感谢您预先提供的帮助。

背景/问题:Cisco Nexus 设备在命令输出中使用“#”和“#”,这会影响在发送下一个命令之前使用相同字符识别命令提示符的脚本逻辑。

我可以通过使用命令提示符的这个更具体的定义来解决大多数问题:

set prompt {([A-Z,a-z,0-9]+)(%|#|>|\\$)[\\ ]?$}

然后在脚本中:

expect -re $prompt
send "$cmd\r"

现在我想通过在正则表达式的开头添加一个尖括号“^”来使这个正则表达式更加具体,“行首,然后是提示符”,但这失败了,脚本在发送之前总是运行超时下一个命令。

set prompt {(^[A-Z,a-z,0-9]+)(%|#|>|\\$)[\\ ]?$}

这也失败了

set prompt {^([A-Z,a-z,0-9]+)(%|#|>|\\$)[\\ ]?$}

在日志文件中,我看到命令提示符前面有 CR(^M,0x0d)。

更奇怪的是,这仍然可以正常工作而不会超时,所以是的,在 Cisco CLI 提示符前有一个 CR:

set prompt {[\x0d]([A-Z,a-z,0-9]+)(%|#|>|\\$)[\\ ]?$}

但在使用“^”时并非如此

set prompt {^[\x0d]([A-Z,a-z,0-9]+)(%|#|>|\\$)[\\ ]?$}

当使用 less 浏览日志文件时,我看到:

^MDevice123# term len 0^M
^MDevice123# show inventory^M

Hexdump 在行尾和新行之间显示提示:

0d 0d 0a 0d (CR CR LF CR)

任何线索我的目标出了什么问题,通过描述从行首到行尾的提示来使命令提示符的正则表达式更加具体?

标签: regextclexpect

解决方案


^将匹配缓冲区的开头,而不仅仅是行的开头。

由于 expect 是基于 Tcl 构建的,因此您可以使用Tcl 正则表达式语法来指示您要^匹配任何换行符之后的空字符串:

set prompt {(?n)^[[:alnum:]]+[%#>$]\s?$}
# ..........^^^^

笔记:

  • 在括号表达式中,使用逗号意味着您也想匹配逗号。而不是[A-Z,a-z,0-9]您想要[A-Za-z0-9]匹配字母或数字,或者使用如上所示的字符类。
  • 我怀疑您不需要捕获括号中的位。

扩展最后一点,当你这样做时:

set prompt {([A-Za-z0-9]+)(%|#|>|\\$)[\\ ]?$}
expect -re $prompt

现在假设它按预期工作。还假设您的提示看起来像:

myHostname1234>

之后expect,expect 会将捕获的正则表达式部分保存在expect_out数组中:

  • $expect_out(0,string)将包含正则表达式匹配的文本
  • $expect_out(1,string)将包含由“([A-Za-z0-9]+)”捕获的字母和数字,在本例中为“myHostname1234”
  • $expect_out(2,string)将包含由“(%|#|>|\$)”捕获的提示符号,在本例中为“>”

我怀疑您没有expect_out在代码中使用该变量,因此无需为存储匹配的文本而烦恼。我怀疑你真的不在乎提示符号是什么。

我知道括号需要对正则表达式的部分进行分组。但是,如果您不需要记住匹配的文本,您可以使用(?:subpattern)获取分组行为而不需要记住行为。

expect_out数组还包含其他内容。阅读期望手册页以了解所有详细信息。


推荐阅读