3

I can't get this to work and am not sure why. I have a line that has spaces between numbers at the end of the line. I need Expect to match this line and put the numbers and spaces into a capture group and I need to access that capture group later in my script.

A sample line is: this is a line 2 4 5 6

My expect -re statement: expect -re {^this\sis\sa\sline((\s\d)+$)}

I am then trying to access the capture group using $expect_out(1,string)

If I check http://gskinner.com/RegExr/ it says match group 1 is "2 4 5 6" so I'm pretty sure the pattern is matching right and I would expect to see "2 4 5 6" in $expect_out(1,string), right?

However, when I run my expect script, I am seeing:

expect: does " \u001b[Js\u001b[Jt\u001b[Jr\u001b[Je\u001b[Ja\u001b[Jm\u001b[Js\u001b[J\r\n\u001b[H\u001b[J\r\n\r\n\r\n\r\this is a line 2 4 5 6\r\n\r\nSelect which option you would    like to change\r\nusing the index number: " (spawn_id exp5) match regular expression "^this\sis\sa\sline((\s\d)+$)"? Gate "this?is?a?line*"? gate=yes re=no
expect: timed out
can't read "expect_out(1,string)": no such element in array
while executing
"set streams $expect_out(1,string)"
(file "check-config" line 35)

How can I get "2 4 5 6" (or " 2 4 5 6") into a variable to use later in my expect script?

Also, while I have your attention, what does Gate=Yes re=No mean? I assume the re=No means the regex didn't match, but what's a Gate in Expect's world?

harperville
  • 5,730
  • 7
  • 23
  • 32

1 Answers1

4

The issue is that you are including line anchors ^ and $ in your regex. The string you're trying to match is clearly a multi-line string, but Tcl's default matching treats newlines just like a regular character. Another complicating factor is that Tcl considers a newline to be \n but expect is using \r\n as the line terminator.

If you enable newline sensitive matching in the regular expression and take the carriage return into account, you may find this regular expression works: (?n)^this\sis\sa\sline((?:\s\d)+)\r?$

Testing:

$ expect <<END
spawn sh -c {echo foo; echo "this is a line 2 4 5 6"; echo bar}
exp_internal 1
expect -re {(?n)^this\sis\sa\sline((?:\s\d)+)\r?$}
END
spawn sh -c echo foo; echo "this is a line 2 4 5 6"; echo bar
Gate keeper glob pattern for '(?n)^this\sis\sa\sline((?:\s\d)+)\r?$' is 'this?is?a?line*'. Activating booster.

expect: does "" (spawn_id exp4) match regular expression "(?n)^this\sis\sa\sline((?:\s\d)+)\r?$"? Gate "this?is?a?line*"? gate=no
foo

expect: does "foo\r\n" (spawn_id exp4) match regular expression "(?n)^this\sis\sa\sline((?:\s\d)+)\r?$"? Gate "this?is?a?line*"? gate=no
this is a line 2 4 5 6
bar

expect: does "foo\r\nthis is a line 2 4 5 6\r\nbar\r\n" (spawn_id exp4) match regular expression "(?n)^this\sis\sa\sline((?:\s\d)+)\r?$"? Gate "this?is?a?line*"? gate=yes re=yes
expect: set expect_out(0,string) "this is a line 2 4 5 6\r"
expect: set expect_out(1,string) " 2 4 5 6"
expect: set expect_out(spawn_id) "exp4"
expect: set expect_out(buffer) "foo\r\nthis is a line 2 4 5 6\r"
glenn jackman
  • 207,528
  • 33
  • 187
  • 305