Expect:从输出中提取特定字符串

2023-12-02

我正在远程计算机上使用 bash 脚本中的 Expect 来导航基于 Java 的 CLI 菜单,并且尝试在不离开 Expect 会话的情况下从输出中提取某些内容。

我的脚本中的 Expect 命令是:

expect -c "
spawn ssh user@host
expect \"#\"
send \"java cli menu command here\r\"
expect \"java cli prompt\"
send \"java menu command\"
"
###I want to extract a specific string from the above output###

预期输出为:

Id       Name
-------------------
abcd 12  John Smith

我想提取abcd 12从上面的输出到另一个期望变量以便在期望脚本中进一步使用。这是第三行,第一个字段,使用双空格分隔符。 awk 等效项是:awk -F ' ' 'NR==3 {$1}'

最大的问题是,正如我上面所说,我使用 Expect 进行导航的环境是一个基于 Java CLI 的菜单,因此我不能只使用 awk 或 bash shell 中可用的任何其他内容。

从 Java 菜单中退出、处理输出然后再次进入并不是一种选择,因为登录过程持续 15 秒,因此我需要留在里面并仅使用 Expect 内部命令从输出中提取我需要的内容。


您可以使用regexp in expect本身直接使用-re旗帜。感谢 Donal 指出单引号和双引号问题。我已经给出了使用两种方式的解决方案。

我创建了一个文件,内容如下,

Id       Name
-------------------
abcd 12  John Smith

这只不过是 java 程序的控制台输出。我已经在我的系统中对此进行了测试。即我刚刚模拟了你的程序的输出cat。您只需更换cat使用您的程序命令进行编码。简单的。 :)

双引号 :

#!/bin/bash
expect -c "
spawn ssh user@domain
expect \"password\"
send \"mypassword\r\"
expect {\\\$} { puts matched_literal_dollar_sign}
send \"cat input_file\r\"; # Replace this code with your java program commands
expect -re {-\r\n(.*?)\s\s}
set output \$expect_out(1,string)
#puts \$expect_out(1,string)
puts \"Result : \$output\"
"

单引号:

#!/bin/bash
expect -c '
spawn ssh user@domain
expect "password"
send "mypasswordhere\r"
expect "\\\$" { puts matched_literal_dollar_sign}
send "cat input_file\r"; # Replace this code with your java program commands
expect -re {-\r\n(.*?)\s\s}
set output $expect_out(1,string)
#puts $expect_out(1,string)
puts "Result : $output"
'

正如你所看到的,我已经使用了{-\r\n(.*?)\s\s}。这里的大括号防止任何变量替换。在您的输出中,我们有一个充满连字符的第二行。然后换行。然后是你的第三行内容。让我们解码所使用的正则表达式。

-\r\n是将一个连字符和一个新行匹配在一起。这将匹配第二行中的最后一个连字符和换行符,而换行符现在又进入第三行。所以,.*?将匹配所需的输出(即 abcd 12),直到遇到与以下内容匹配的双空格\s\s.

您可能想知道为什么我需要用于获取子匹配模式的括号。

一般来说,expect将保存期望的整个匹配字符串expect_out(0,string)并将所有匹配/不匹配的输入缓冲到expect_out(buffer)。每个子匹配将保存在字符串的后续编号中,例如expect_out(1,string), expect_out(2,string)等等。

enter image description here

正如 Donal 指出的,最好使用单引号的方法,因为它看起来不那么混乱。 :)

不需要逃避\r如果有双引号,则使用反斜杠。

Update :

我已经改变了regexp from -\r\n(\w+\s+\w+)\s\s to -\r\n(.*?)\s\s.

通过这种方式 - 您的要求 - 例如match any number of letters and single spaces until you encounter first occurrence of double spaces in the output

现在,让我们来回答你的问题。你提到你已经尝试过-\r\n(\w+)\s\s。但是,这里有一个问题\w+。记住\w+不会匹配空格字符。您的输出中有一些空格,直到双空格。

正则表达式的使用取决于您对要匹配的输入字符串的要求。您可以根据需要自定义正则表达式。

更新版本2:

有什么意义.*?。如果你单独问,我会重复你的评论。在正则表达式中,*是一个贪心运算符并且?是我们的救星。让我们将字符串视为

Stackoverflow is already overflowing with number of users.

现在看看正则表达式的效果.*flow如下。

enter image description here

*匹配任意数量的字符。更准确地说,它匹配尽可能长的字符串,同时仍然允许模式本身匹配。所以,由于这个原因,.*在模式中匹配字符Stackoverflow is already over and flow模式与文本匹配flow在字符串中。

现在,为了防止.*仅匹配字符串第一次出现的位置flow,我们正在添加?到它。它将帮助模式表现得非贪婪的方式。

enter image description here

现在,再次回到你的问题。如果我们已经使用过.*\s\s,那么它将匹配整行,因为它试图尽可能匹配。这是正则表达式的常见行为。

更新版本3:

按以下方式获取代码。

x=$(expect -c "
spawn ssh user@host
expect \"password\"
send \"password\r\"
expect {\\\$} { puts matched_literal_dollar_sign}
send \"cat input\r\"
expect -re {-\r\n(.*?)\s\s}
if {![info exists expect_out(1,string)]} {
        puts \"Match did not happen :(\"
        exit 1
}
set output \$expect_out(1,string)
#puts \$expect_out(1,string)
puts \"Result : \$output\"
")
y=$?

# $x now contains the output from the 'expect' command, and $y contains the
# exit status
echo $x
echo $y;

如果流程正确,则退出代码的值为 0。否则,它将为 1。通过这种方式,您可以检查 bash 脚本中的返回值。

看一下here了解有关info exists命令。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Expect:从输出中提取特定字符串 的相关文章

  • 有没有办法将 Python/Tkinter 连接到已经运行的 Tcl/Tk 应用程序?

    我在 Pure Data 上做了很多工作 这是一个用 Tcl Tk 和 C 编写的应用程序 我希望能够为修改 Tcl Tk GUI 的插件制作一个 python API 为此 我似乎需要能够将正在运行的 Tk 实例传递给 python 然后
  • 如何使用 Swig 将枚举值从 TCL 脚本传递到 C++ 类

    我正在使用以下代码 1 文件 example i module example Put header files here or function declarations like below include example h incl
  • TCL/Expect - exec - 如何使用参数执行程序

    我正在尝试使用 TCL 命令exec in tclsh这是我的结果 set show me dir ls ls exec show me dir VboxSharedFolder set show me dir ls la ls la ex
  • 生成和执行之间有什么区别?

    我正在学习编写 TCL 期望 脚本 我注意到一些示例显示了如何使用 spawn 而其他示例则显示了命令 exec 我尝试谷歌搜索 但找不到有什么区别 假设我在一个很长的期望脚本中间调用 exec 我会期望发生什么 spawn is an e
  • 如何使用带有可选提示的expect?

    假设我正在尝试为具有三个提示的 test sh 编写一个 Expect 脚本 prompt1 prompt2 prompt3 我的代码是这样的 spawn test sh expect prompt1 send pass1 expect p
  • 如何编写具有默认值和选项的 tcl 程序?

    我正在尝试编写一个 tcl 程序 它执行以下操作 proc myProc arg1 def1 arg2 def2 tcl gt myProc arg1 val1 arg2 val2 arg1 variable has val1 arg2 v
  • 如何使用tcl中的puts更改文本颜色

    我想通过使用 tcl 中的 put 命令来更改控制台中显示的文本颜色以简化调试 我看到很多文章是 abt tk 而不是 tcl 仅供参考 我在 Windows 7 上使用 Active tcl 我尝试过其他人提供的以下代码 http www
  • 黑莓开发上的脚本语言?

    据我所知 开发 Blackberry 应用程序的首选方法是 Java 这是吗only way 我梦想有一个快速的应用程序环境 您可以在其中创建 GUI 使用 Blackberry UI 组件 类似于 Blackberry 上的 Tcl Tk
  • Tcl + 检查文件存在

    我正在尝试检查 Tcl 中是否存在文件 但我似乎无法得到真实的结果 尽管我知道它的存在 while true if file exists file name 1 exp send copy file txt destination r p
  • 按值对 Tcl 字典排序

    我想知道 Tcl 中是否有一种按值对 dict 进行排序的优雅方法 假设我有以下字典 set d1 dict create k1 10 k2 89 k3 1 k4 15 k5 20 Results in dict of form k1 gt
  • 如何使用 Python 在同一 TCL shell 上运行命令

    我所有的库都是用 TCL 编写的 我想用 Python 创建一个 GUI 其中有几个按钮和其他选项 在启动时TCL shell会打开 当我单击按钮时 将在 TCL shell 上执行相应的命令 是否可以在不关闭 TCL shell 的情况下
  • 在 Tkinter 中处理触摸屏手势

    我将如何在 Tkinter 中安装触摸屏手势处理程序 我需要一些特别简单的事情 每当检测到 展开 手势时就增加字体大小 如果 Tcl Tk 没有具体实现的话 这是否可以在 Tkinter 中实现 我想要么窗口管理器向客户端窗口发送一些我可以
  • 使用expect进行无人值守(无提示)Homebrew安装

    根据Homebrew安装说明 可以使用以下命令进行安装 ruby e curl fsSL https raw github com Homebrew homebrew go install 这可行 但需要用户输入两次 确认安装并在脚本调用的
  • Tcl 脚本中错误的静态检测

    我已经开发了一些代码 并且在 Linux 机器上遇到了 Tcl 解释器错误标记的问题 usr bin tclsh if 1 puts abc1 elseif puts abc2 上面的代码没有标记错误 elseif 条件 直到进入elsei
  • Windows 上的 unbuffer 程序相当于什么?

    你好根据这个帖子 https unix stackexchange com a 25375 unbuffer通过伪终端 pty 连接到命令 这使得系统将其视为交互式进程 因此不使用任何 stdout 缓冲 我想在 Windows 上使用这个
  • 如何让proc更有效?

    有一个顶点集合 x1 y1 x2 y2 xn yn 我想改变这些坐标的中心 所以我尝试 proc changeCenter vertices X Y set myList list foreach element vertices lapp
  • 如何使用 bash/expect 检查 SSH 登录是否有效

    我的团队管理着许多服务器 公司政策规定这些服务器上的密码必须每隔几周更改一次 有时 我们的官方密码数据库会因某种原因而过时 人们通常会忘记更新它 但有时我们要到几个月后才能识别这一点 因为我们并不总是使用每台服务器 我想编写一个脚本 从数据
  • 在 bash 中使用 ssh 内的 Expect 执行 sudo

    我想创建一个脚本来自动在多个 Linux 主机上进行安装 我使用 ssh 密钥登录到主机 在登录中我想做一个 sudo 我正在尝试使用 Expect 我在站上有它 但是我的服务器上没有运行脚本 我该怎么做 这是我的尝试 但没有运气 bin
  • 在expect脚本中发送INSERT和F12

    我知道为了在期望脚本中发送返回 我会执行以下操作 send r What is the send command for the INSERT and F12 keys I ve looked online and cannot find
  • 从 Bash 调用的 Expect 脚本的退出状态代码

    我制作了一个 Bash 脚本 它使用 Expect 脚本来自动进行 ssh 登录 该脚本连接到多个服务器并运行一些命令 bash 脚本会提示输入一次登录凭据 我想合并一个功能 其中如果第一个服务器登录失败 脚本将终止 以避免脚本检查下一个服

随机推荐