1
votes

I have an EXPECT script that monitors the http pid's on an IBMIHS server:

    ....
    send "ps -ef|grep htt|grep start|wc -l \r"
    expect {
       -re {.*(\d+).*} {

          set theNum $expect_out(1,string)
      }
    }

    puts "theNum = $theNum"

    if {$theNum > 8} {
      puts "it is ok"
    } else {
      puts "it is not ok"
    }
....

The send "ps -ef|grep htt|grep start|wc -l \r" generates:

send: sending "ps -ef|grep htt|grep start|wc -l \r" to { exp5 }
Gate keeper glob pattern for '.(\d+).' is ''. Not usable, disabling the performance booster.

expect: does "" (spawn_id exp5) match regular expression ".(\d+)."? (No Gate, RE only) gate=yes re=no
ps -ef|grep htt|grep start|wc -l

expect: does "ps -ef|grep htt|grep start|wc -l \r\n" (spawn_id exp5) match regular expression ".(\d+)."? (No Gate, RE only) gate=yes re=no
11

expect: does "ps -ef|grep htt|grep start|wc -l \r\n11\r\n" (spawn_id exp5) match regular expression ".(\d+)."? (No Gate, RE only) gate=yes re=yes

expect: set expect_out(0,string) "ps -ef|grep htt|grep start|wc -l \r\n11\r\n"
expect: set expect_out(1,string) "1"
expect: set expect_out(spawn_id) "exp5" expect: set expect_out(buffer) "ps -ef|grep htt|grep start|wc -l \r\n11\r\n"
theNum = 1
it is not ok

The command line actually returns a number "11", but the (\d+) catches one '1' instead.

Your comments are appreciated in advance.

1

1 Answers

3
votes

It's due to the greediness of the leading .* -- because that slurps up as many characters as possible, the text remaining for the (\d+) part is the last digit. Here's a demo where I also capture the leading ".*":

expect1.11> exp_internal 1
expect1.12> spawn sh -c {echo foo; echo 1234; echo bar}
spawn sh -c echo foo; echo 1234; echo bar
parent: waiting for sync byte
parent: telling child to go ahead
parent: now unsynchronized from child
spawn: returns {78523}
78523
expect1.13> expect -re {(.*)(\d+).*}
Gate keeper glob pattern for '(.*)(\d+).*' is ''. Not usable, disabling the performance booster.

expect: does "" (spawn_id exp10) match regular expression "(.*)(\d+).*"? (No Gate, RE only) gate=yes re=no
foo
1234
bar

expect: does "foo\r\n1234\r\nbar\r\n" (spawn_id exp10) match regular expression "(.*)(\d+).*"? (No Gate, RE only) gate=yes re=yes
expect: set expect_out(0,string) "foo\r\n1234\r\nbar\r\n"
expect: set expect_out(1,string) "foo\r\n123"
expect: set expect_out(2,string) "4"
expect: set expect_out(spawn_id) "exp10"
expect: set expect_out(buffer) "foo\r\n1234\r\nbar\r\n"

Take note of what gets stored in "1,string" and "2,string"

The solution is to simplify your regex. If you just want to capture the first set of digits, use

expect -re {\d+}
set theNum $expect_out(0,string)

Or if you want to capture the first digits that are the only chars on a line:

expect -re {\r\n(\d+)\r\n}
set theNum $expect_out(1,string)

One lesson here is that you generally don't need to have leading and ending .* wildcards in your regular expression patterns: just focus on what you need to capture the text you want.