0

I am a newbie in expect / TCL and trying to parse an HTML page that has output some thing like below:

<li><p>Timestamp: Wed, 14 Nov 2012 16:37:50 -0800
<li><p>Your IP address: 202.76.243.10</p></li>
<li><p class="XXX_no_wrap_overflow_hidden">Requested URL: /</p></li>
<li><p>Error reference number: 1003</p></li>
<li><p>Server ID: FL_23F7</p></li>
<li><p>Process ID: PID_1352939870.809-1-428432242</p></li>
<li><p>User-Agent: </p></li>

My script is below. I am able to get the web page which I am not able to parse the line "Your IP address:" which is giving me errors:

#!/usr/bin/expect -f
set timeout -1
spawn telnet www.whatismyip.com 80
send "GET /\r\n"
expect
set output $expect_out(buffer)
foreach line [split $output \n] {
        regexp {.*<li><p>Your IP Address Is:.*?(\d+\.\d+\.\d+\.\d+)} $line ip
        if {[string length ${ip}]} {
                puts $ip
    }
}

The error is:

    Connection closed by foreign host.
can't read "ip": no such variable
    while executing
"string length ${ip}"
    ("foreach" body line 3)
    invoked from within
"foreach line [split $output \n] {
        regexp {.*<li><p>Your IP Address Is:.*?(\d+\.\d+\.\d+\.\d+)} $line ip
        if {[string length ${ip}]} {
 ..."
    (file "./t4" line 7)

Any pointers where I am doing wrong?

4

3 回答 3

1

正则表达式不匹配,因此未分配变量。您应该检查结果regexp以查看匹配是否成功;当不使用-allto 选项时regexp,您可以将其视为布尔值。尝试这个:

foreach line [split $output \n] {
    if {[regexp {<li><p>Your IP Address Is:.*?(\d+\.\d+\.\d+\.\d+)(?!\d)} $line -> ip]} {
        puts $ip
    }
}

->确实是一个(奇怪的!)变量名,它将保存整个匹配的字符串;我们对它不感兴趣(只是括号部分),所以我们使用非字母来助记“这将到那里”(ip变量的子匹配)。

于 2012-11-15T01:51:22.573 回答
1

您的行包含“地址”(小写),但您尝试匹配“地址”(大写)。将
-nocase选项添加到 regexp 命令。此外,Tcl 正则表达式不能混合贪婪——第一个量词确定整个表达式是贪婪还是非贪婪(我现在找不到记录在哪里)。

regexp -nocase {IP Address.*(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})} $line -> ip
于 2012-11-15T02:33:31.810 回答
0

如果您的最终目标是获取主机的外部 IP,请使用 API 解决方案,例如来自 exip.org 的解决方案:

#!/usr/bin/env tclsh

set api http://api-nyc01.exip.org/?call=ip
if {[catch {exec curl --silent $api} output]} {
    puts "Failed to acquire external IP"
} else {
    puts "My external IP is $output"
}

请访问他们的API站点以获取更多信息,尤其是如果您居住在美国境外。此解决方案需要curl,您可能需要安装它。

于 2012-11-15T15:01:07.113 回答