我是expect / TCL中的新手并试图解析输出如下所示的HTML页面:
<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>
我的脚本如下。我能够获得一个网页,我无法解析“你的IP地址:”这一行给我的错误:
#!/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
}
}
错误是:
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)
我做错了什么指针?
答案 0 :(得分:1)
正则表达式不匹配,因此未分配变量。您应该检查regexp
的结果以查看匹配是否成功;如果不使用-all
regexp
选项,则可以将其视为布尔值。试试这个:
foreach line [split $output \n] {
if {[regexp {<li><p>Your IP Address Is:.*?(\d+\.\d+\.\d+\.\d+)(?!\d)} $line -> ip]} {
puts $ip
}
}
->
实际上是一个(奇怪的!)变量名,它将保存整个匹配的字符串;我们对它不感兴趣(只是括号部分),所以我们使用非字母表来大声说“这将转到那里”(与ip
变量的子匹配)。
答案 1 :(得分:1)
您的行包含“地址”(小写),但您尝试匹配“地址”(大写)。添加
regexp命令的-nocase
选项。此外,Tcl正则表达式不能具有混合贪婪 - 第一个量词确定整个表达式是贪婪还是非贪婪(我现在无法找到记录的位置)。
regexp -nocase {IP Address.*(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})} $line -> ip
答案 2 :(得分: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
,您可能需要安装该解决方案。