Search code examples
regexexpect

exclude everything except ip address via regexp


sh ip cef | i 0.0.0.0.*Vlan9
0.0.0.0/0            192.168.18.200          Vlan9

I want to take only the ip address from it, that is, exclude 0.0.0.0/0 and Vlan9

I try it through expect, but for some reason it doesn't work

(?!Vlan9|0)\d+.\d+.\d+.\d+

expect -exact "#"
send -- "sh ip cef | i 0.0.0.0.*Vlan9 \r"
expect -exact "#"
set dst $expect_out(buffer)
regexp {(?!Vlan9|0)\d+.\d+.\d+.\d+} $dst match ipdst
#expect -exact "#"
#send -- "clear ip arp $ipdst\r"
#expect -exact "#"
puts "router is dst ip $ipdst"

by the way, expect -exact "#" - judging by the debug, it outputs each character on a separate line and does the gluing?

LOG

./ssh 192.168.18.200

/***  DATE is Wed Mar 17 12:42:57 MSK 2021 ***/

spawn ssh -o StrictHostKeyChecking=no test@192.168.18.200
parent: waiting for sync byte
parent: telling child to go ahead
parent: now unsynchronized from child
spawn: returns {28141}

expect: does "" (spawn_id exp6) match glob pattern "*assword:"? no
Password:
expect: does "\rPassword: " (spawn_id exp6) match glob pattern "*assword:"? yes
expect: set expect_out(0,string) "\rPassword:"
expect: set expect_out(spawn_id) "exp6"
expect: set expect_out(buffer) "\rPassword:"
send: sending "123456\r" to { exp6 }
send: sending "sh ip cef | i 0.0.0.0.*Vlan9 \r" to { exp6 }

expect: does " " (spawn_id exp6) match glob pattern "#"? no


expect: does " \r\n" (spawn_id exp6) match glob pattern "#"? no

Solution

  • Please try:

    regexp {(?!Vlan9|0)(\d+\.\d+\.\d+\.\d+)} $dst match ipdst
    

    or:

    regexp {(?!Vlan9|0)\d+\.\d+\.\d+\.\d+} $dst ipdst
    
    • You need to surround the regex with parentheses to capture the submatch. In the second statement above, ipdst is assigned to the whole matched substring, which also makes a sense.
    • You need to escape the literal dot, otherwise it will match any character.

    [EDIT]
    If your expect version does not support lookaround assertions, please try instead:

    regexp {(\d+\.\d+\.\d+\.\d+)\s+Vlan9} $dst match ipdst
    

    or as a last resort:

    regexp {([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)[^0-9]+Vlan9} $dst match ipdst
    

    which will work with very old expect or tcl.

    [EDIT]
    Here is an example of ssh login transaction:

    #!/usr/bin/expect
    
    set host "localhost"            ;# change to your server name
    set user "guest"                ;# user name
    set pass "secret123"            ;# password
    
    spawn ssh $host -l $user
    expect "assword:"
    send "$pass\n"
    expect "Last login:"
    expect "\$ "                    ;# command prompt (may differ depending on the system)
    send "hostname\n"               ;# just an example; replace with your preferred command
    expect "\n"                     ;# newline of the echo back of the sent command
    expect "*\n"                    ;# wait for the server's response
    set response $expect_out(0,string)
    puts "server's response is $response"