Tcl Expect:错误可以';“我不读”;知识产权:没有这样的变量
我是expect/TCL的新手,正在尝试解析输出如下内容的HTML页面:Tcl Expect:错误可以';“我不读”;知识产权:没有这样的变量,tcl,expect,Tcl,Expect,我是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><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>
时间戳:2012年11月14日星期三16:37:50-0800
#!/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
}
}
#/usr/bin/expect-f
设置超时-1
spawn telnet www.whatismyip.com 80
发送“GET/\r\n”
期待
设置输出$expect\u out(缓冲区)
foreach行[拆分$output\n]{
regexp{.*您的IP地址是:.*(\d+\.\d+\.\d+\.\d+}$line IP
如果{[string length${ip}]}{
卖出$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)
连接已被外部主机关闭。
无法读取“ip”:没有此类变量
执行时
“字符串长度${ip}”
(“foreach”正文第3行)
从内部调用
“foreach行[拆分$output\n]{
regexp{.*您的IP地址是:.*(\d+\.\d+\.\d+\.\d+}$line IP
如果{[string length${ip}]}{
..."
(文件“/t4”第7行)
是否有我出错的指针?正则表达式不匹配,因此未分配变量。您应该检查
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
}
}
foreach行[拆分$output\n]{
如果{[regexp{您的IP地址是:.*(\d+\.\d+\.\d+\.\d+(?!\d)}$line->IP]}{
卖出$ip
}
}
->
确实是一个(奇怪的!)变量名,它将保存整个匹配的字符串;我们对它不感兴趣(只是插入的部分),所以我们使用非字母形式的助记符来表示“这就要到那里了”(与ip
变量的子匹配)。您的行包含“地址”(小写)但是您正在尝试匹配“地址”(大写)。添加regexp命令的-nocase选项。此外,Tcl正则表达式不能具有混合贪婪性——第一个量词确定整个表达式是贪婪的还是非贪婪的(我现在找不到记录在哪里)
如果您的最终目标是获得主机的外部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"
}
请访问他们的网站了解更多信息,特别是如果您居住在美国境外。此解决方案需要
curl
,您可能需要安装。谢谢,它可以工作,但IP值仅被其最后一个字符值截断。我的代码是如果{[regexp{(?!\d)
:“下一位没有数字”)“真的很糟糕的技术原因”这与Tcl使用自动机理论的重新引擎而不是基于堆栈的PCRE及相关系统有关。实现这一点的代码绝对不是琐碎和可怕的复杂。我自己,我总是尝试编写完全贪婪的重新引擎;很久以前我就是这样被教导的,他们的行为(相对而言)很容易理解。最初的RE是您提供的,但是由于您并不真正需要它,所以去掉了前面的*
,但这迫使RE的其余部分被解释为贪婪的…我没有发现。哦,好吧!顺便说一句,试着使用http包:包需要http;设置tok[http::geturl www.whatismyip.com];如果{[regexp{您的IP地址是:.*(\d+\.\d+\.\d+\.\d+.\d+(!\d)}[http::data$tok]>IP]}{put$IP};http::cleanup$tok
与我在这里得到的值相同-如前所述,ip值被最后一个字符截断-如果标记值是ip地址:202.76.243.10我得到的'put$ip'为202.76.243.1-最后的0被忽略
#!/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"
}