您可以使用regexp
在expect
本身直接使用-re
标志。感谢Donal指出单引号和双引号问题。我已经用两种方法给出了解决方案。
我已经创建了内容的文件,如下所示,
Id Name
-------------------
abcd 12 John Smith
这不过是你的java程序的控制台输出。我已经在我的系统中对此进行了测试。即我只是用cat
来模拟你的程序输出。您只需使用程序命令替换cat
代码即可。简单。 :)
双引号:
#!/bin/bash
expect -c "
spawn ssh [email protected]
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 [email protected]
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)
等等。
正如多纳尔指出的那样,最好使用单引号的方法,因为它看起来不太凌乱。 :)
如果是双引号,则不需要用反斜杠来转义\r
。
更新:
我从-\r\n(\w+\s+\w+)\s\s
改变regexp
到-\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
如下的效果。
*
匹配任何数目的字符。 更确切地说,它匹配的字符串,最长的可能,同时仍允许模式本身相匹配。因此,由于这个原因,.*
在模式匹配的字符Stackoverflow is already over
和模式flow
匹配的字符串文本flow
。
现在,为了防止.*
仅匹配字符串flow
的第一个匹配项,我们将?
添加到它。这将有助于该模式表现为非贪婪的态度。
现在,再来回到你的问题。如果我们使用.*\s\s
,那么它将整条生产线,因为它正试图尽可能地匹配匹配。这是正则表达式的共同行为。
更新版本3:
在下列方式你的代码。
x=$(expect -c "
spawn ssh [email protected]
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
命令。
问题的核心在于你试图将期望脚本放入双引号的shell文本中。这会迫使你使用_Lots_的反斜杠引用。虽然您可以这样做,但将期望脚本放在自己的文件中(例如'mydostuff.exp')会使一切变得简单。然后你可以用'expect mydostuff.exp'运行它... – 2014-11-23 23:21:47