Para dizer a conclusão primeiro,
(e obrigado@alfredormz para isso!)
a forma mais elegante e rápida é esta:
dig +short myip.opendns.com @resolver1.opendns.com
Isso pede o endereço IP do myip.opendns.com
servidor de nomes resolver1.opendns.com
(algo em que você confia),
que retornará seu endereço IP externo.
Se não tiver dig
,
você pode usar estas alternativas:
curl ipecho.net/plain
curl icanhazip.com
curl curlmyip.com
curl l2.io/ip
curl ip.appspot.com
curl ifconfig.me/ip
curl eth0.me
Ou se você precisar no formato JSON:
curl httpbin.org/ip
curl wtfismyip.com/json
Eles funcionam em HTTP
e , portanto, menos eficientes do que a consulta DNS direta com dig
.
Ao usar qualquer uma dessas soluções,
lembre-se de que você está contando com serviços externos.
Eles podem estar indisponíveis temporariamente ou mesmo permanentemente em algum ponto.
Portanto, nenhum desses é perfeito.
Este artigo é, na verdade, sobre outra coisa.
É sobre o desafio de extrair as partes relevantes de um texto curto.
Recentemente, precisei extrair meu endereço IP externo de http://monip.org/ usando ferramentas de linha de comando.
Este artigo é sobre como explicar o processo de pensamento,
caso você precise de algo semelhante.
Vamos ver o que conseguimos com um simples curl
:
$ curl monip.org
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>MonIP.org v1.0</title>
<META http-equiv="Content-type" content="text/html; charset=ISO-8859-1">
</head>
<P ALIGN="center"><FONT size=8><BR>IP : 67.205.36.164<br></font><font size=3><i>genovese.dreamhost.com</i><br></font><font size=1><br><br>Pas de proxy d�tect� - No Proxy detected</font></html>
Uma maneira de extrair o endereço IP disso é usando sed
:
$ curl -s monip.org | sed -n 's/.*IP : ([0-9.]*).*/1/p'
67.205.36.164�tect� - No Proxy detected</font></html>
Ugh. Quase funciona, mas quase:
sobra um pouco de lixo no final.
Eu realmente não sei por que o .*
no final não apagou tudo após o endereço IP.
Parece que sed
tem problemas com alguns personagens não ASCII.
Olhando para a saída original,
parece que o site usa a codificação ISO-8859-1,
então , se colocarmos um iconv
no pipeline, ele pode corrigir o problema:
$ curl -s monip.org | iconv -f iso-8859-1 | sed -n 's/.*IP : ([0-9.]*).*/1/p'
67.205.36.164
Muito melhor! Vamos ver como isso sed
funciona:
Por padrão,
sed
ecoa as linhas que processa.
O sinalizador desliga isso: ele apenas imprimirá qualquer coisa com comandos de impressão explícitos.-n
Uma técnica para extrair um padrão de algum corpo de texto está utilizando a expressão: . O na substituição é uma referência anterior ao padrão que foi correspondido na primeira expressão. O antes e o depois do padrão de interesse devem fazer com que o padrão de pesquisa corresponda a toda a linha, de modo que o resultado da substituição seja a linha inteira substituída pelo padrão de interesse.
s/.*(pattern).*/1/
1
(...)
.*
Usamos como padrão. Esta é uma abordagem imprecisa, preguiçoso, e nós poderia ter sido muito mais precisa, por exemplo: . Depende de você e da tarefa dada onde você traça a linha.
.*IP : ([0-9.]*).*
.*IP : ([0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3})>.*
A
p
bandeira no idioma faz imprimir a linha apenas se houver uma substituição. Isso é perfeito para o nosso propósito: desta forma só será impressa a linha com o endereço IP, após a substituição, então a saída será simplesmente o próprio endereço IP.s///p
sed
A propósito,
quando eu fiz isso pela primeira vez, o problema de codificação com sed
minha primeira reação foi usar perl
:
curl -s monip.org | perl -ne '/IP : ([0-9.]+)/ && print $1'
Ele usa a lógica de extração equivalente como no anterior sed
,
com algumas diferenças devido à natureza dessas ferramentas:
O sinalizador é para executar uma expressão Perl fornecida na linha de comando, em oposição a um arquivo especificado.
-e
O sinalizador envolve a expressão dentro de um bloco, tornando-o adequado para o processamento de entrada padrão linha por linha.
-n
while (<>) { ... }
A correspondência de padrões é um pouco mais simples em comparação com
sed
,
porquesed
usa expressões regulares básicas (BRE),
e Perl usa PCRE, que é muito mais avançado.Em Perl, você pode usar para trás referências a padrões capturados dentro de
(...)
expressões usando as variáveis$1
,$2
e assim por diante.O idioma significa, se o padrão foi correspondido, imprimir o conteúdo do primeiro grupo.
/(pattern)/ && print $1