Ожидание: ошибка не может прочитать "IP": нет такой переменной
Я новичок в ожидайте / 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)
Любые указатели, где я делаю не так?
3 ответа
Регулярное выражение не соответствует, поэтому переменная не была назначена. Вы должны проверить результат 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
переменная).
Если вашей конечной целью является получение внешнего 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
, который вам может понадобиться установить.
Ваша строка содержит "адрес" (в нижнем регистре), но вы пытаетесь сопоставить "адрес" (в верхнем регистре). Добавить-nocase
опция для команды regexp. Кроме того, регулярные выражения Tcl не могут иметь смешанную жадность - первый квантификатор определяет, является ли все выражение жадным или не жадным (я не могу найти, где это задокументировано прямо сейчас).
regexp -nocase {IP Address.*(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})} $line -> ip