Ожидание: ошибка не может прочитать "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
Другие вопросы по тегам