【问题标题】:Extracting an IP address to a variable using Expect script使用 Expect 脚本将 IP 地址提取到变量中
【发布时间】:2012-10-19 03:45:45
【问题描述】:

您好,我是 Expect 脚本的新手,我一直在尝试使用以下方法将 IP 地址提取到变量中:

set timeout -1
spawn $env(SHELL)
match_max 100000
send "ifconfig | grep -A 1 'eth1' | tail -1\r "
expect -re "inet addr:.* " {send "ping $expect_out(0,string)\r"}
send -- "exit\r"
expect eof

问题是它试图用 ifconfig 命令的结果进行 ping,其中包含一些字符串字符。

谁能帮我从 ifconfig 命令中提取 IP 地址并将其存储在变量中?我也一直在使用 $expect_out(buffer) ,但就是无法理解它。非常感谢您对这些方面的任何帮助。

【问题讨论】:

    标签: expect ifconfig


    【解决方案1】:

    您不需要生成 shell:

    spawn ifconfig eth1
    expect -re {inet addr:(\S+)}
    set ipaddr $expect_out(1,string)
    expect eof
    
    spawn ping -c 10 $ipaddr
    expect eof
    

    事实上,您不需要在纯 Tcl 中使用 Expect:(对 ping 进行额外的错误检查):

    if {[regexp {inet addr:(\S+)} [exec ifconfig eth1] -> ipaddr]} {
        set status [catch [list exec ping -c 10 $ipaddr] output]
        if {$status == 0} {
            puts "no errors from ping: $output"
        } else {
            puts "ERROR: $output"
        }
    }
    

    【讨论】:

    • +1 我喜欢这种方法。以这种方式生成命令有什么好处,而不是使用带有“catch”命令的 exec 来存储输出? (即捕获 { exec ping 192.168.0.1} pingresults )
    • 这取决于您只需要与生成的程序交互多少。如果您只需要它运行并捕获输出和退出状态,请使用exec。 (请参阅this tcl wiki article 以了解正确的 exec 处理——向下滚动并单击“显示讨论”)如果生成的程序需要您响应提示,请使用 spawn/expect/send。
    • 谢谢-我会检查链接。交互角度当然是有道理的——也许我真的想知道一种方法是否比另一种更“安全”或“安全”。
    【解决方案2】:

    您可以在现有代码上使用regexp

    expect -re "inet addr:.* " {
      regexp {inet.*?(\d+\.\d+\.\d+\.\d+)} $expect_out(buffer) match ip
      puts "Pinging $ip"
      send "ping $ip\r"
    }
    

    行内:

    regexp {inet.*?(\d+\.\d+\.\d+\.\d+)} $expect_out(buffer) match ip
    

    regexp 命令在括号中的“捕获组”中捕获 ip 地址:

    (\d+\.\d+\.\d+\.\d+)

    然后将其存储在变量ip 中。

    expect_out(buffer) 变量是源字符串,包含到目前为止通过期望读取的所有内容(直到您的expect -re 命令),match 是另一个变量,它存储与整个正则表达式匹配的字符串(来自 'inet ' 到 IP 地址的末尾。)match 只是为了符合正则表达式语法,即要求在捕获组之前存在一个变量 - 在这个特定示例中它是一次性数据 - 正则表达式的重新设计版本可以使用 match存储此示例的 ip,但总的来说,我发现捕获组更灵活,因为您可以有多个从单个字符串中捕获不同的数据。

    您可能需要阅读regexp 命令和一般的regular expressions,因为Expect 对它们进行了相当广泛的使用。

    【讨论】:

    • 非常感谢您的回复。它完美无缺。还可以阐明在期望(缓冲区)和匹配 IP 方面发生了什么魔术。 match 是如何从期望缓冲区中提取 ipaddress 的。请在上面写几行。非常感谢您的青睐。
    • 编辑了我的答案以添加更多细节。
    • 您好,感谢您提供信息丰富的回复。我这里还有一个问题。 ipaddress 的最后一位被截断,然后存储在变量 "ip" 中。例如: 138.231.50.8 而不是正确的 138.231.50.80 .. 知道为什么...??
    • 试试 rubular.com 作为调整正则表达式的工具。还要确保 $expect_out(buffer) 填充了它需要的所有数据,您的 expect -re 语句可能在整行打印到标准输出之前匹配。使用 puts 语句对其进行故障排除。
    【解决方案3】:

    将您的“发送"ifconfig | grep -A 1 'en1' | tail -1\r"”更改为如下所示。

    send "ifconfig | grep -A 1 'en1' | tail -1 | cut -d' ' -f2\r"

    【讨论】:

      【解决方案4】:
      $ifconfig 
      eth0      Link encap:Ethernet  HWaddr 00:1b:fc:72:84:12  
            inet addr:172.16.1.13  Bcast:172.16.1.255  Mask:255.255.255.0
            inet6 addr: fe80::21b:fcff:fe72:8412/64 Scope:Link
            UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
            RX packets:638661 errors:0 dropped:20 overruns:0 frame:0
            TX packets:93858 errors:0 dropped:0 overruns:0 carrier:2
            collisions:0 txqueuelen:1000 
            RX bytes:101655955 (101.6 MB)  TX bytes:42802760 (42.8 MB)
            Memory:dffc0000-e0000000 
      
      lo        Link encap:Local Loopback  
            inet addr:127.0.0.1  Mask:255.0.0.0
            inet6 addr: ::1/128 Scope:Host
            UP LOOPBACK RUNNING  MTU:16436  Metric:1
            RX packets:3796 errors:0 dropped:0 overruns:0 frame:0
            TX packets:3796 errors:0 dropped:0 overruns:0 carrier:0
            collisions:0 txqueuelen:0 
            RX bytes:517624 (517.6 KB)  TX bytes:517624 (517.6 KB)
      

      试试这个:

      ifconfig | sed '2,2!d' | sed 's/.*addr://' | sed 's/\ .*//' > ipaddress
      

      这将给出 ip

      $vi ipaddress 
      

      【讨论】:

        猜你喜欢
        • 2011-06-10
        • 2014-02-15
        • 1970-01-01
        • 2022-08-19
        • 1970-01-01
        • 2013-06-10
        • 1970-01-01
        • 1970-01-01
        • 2013-01-26
        相关资源
        最近更新 更多