Como selecionar e imprimir o endereço IP de um conjunto de seqüências de caracteres?

3

Eu tenho uma frase que contém um endereço IP. Por exemplo,

This sentence contains an ip number 1.2.3.4 and port number 50, i want to print the IP address only.

A partir da frase acima, quero imprimir apenas o endereço IP. Como posso fazer isso? Ouvi dizer que é possível fazer isso com sed

    
por Anandu M Das 21.11.2014 / 14:55

7 respostas

6

É possível, mas não elegante:

echo 'This sentence contains an ip number 1.2.3.4 and port number 50, i want to print the IP address only.' \
| sed 's/.*\([0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\).*//'

[0-9] corresponde a qualquer dígito, \{1,3\} significa que ele pode ser repetido de 1 a 3 vezes. \. corresponde a um ponto. O IP inteiro é capturado pelos \(...\) parênteses, o que vem antes e depois é correspondido por .* , ou seja, qualquer coisa repetida zero ou mais vezes. Toda a string correspondente (ou seja, a linha inteira) é então substituída pelo conteúdo do primeiro grupo correspondente.

Você pode torná-lo mais legível introduzindo uma variável:

n='[0-9]\{1,3\}'
... | sed "s/.*\($n\.$n\.$n\.$n\).*//"

Imprime toda a string se o IP não for encontrado. Ele também não verifica se há IPs inválidos, como 256.512.999.666.

    
por choroba 21.11.2014 / 14:59
6

Esta é uma solução grep :

echo "$sentence" | grep -oE '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+'
  • -o imprime apenas a parte correspondente
  • -E muda para regex estendido
  • o padrão corresponde a cada dígito ( [0-9] ) uma ou mais vezes ( + ), depois um ponto ( \. ) e novamente dígitos ...

Aqui outra solução com perl :

echo "$sentence" | perl -l -ne '/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/ && print $&'
  • -l especificou o terminador de linha (nova linha)
  • -n faz um loop pela entrada dada por echo (podem ser várias linhas)
  • O código -e segue
  • a regex dentro do código perl é praticamente a mesma que na solução grep acima
por chaos 21.11.2014 / 15:16
2

Use este comando de grep :

grep -Eo '[0-9.]+ ' file

Ou melhor ainda:

grep -oP '\d+\.\d+\.\d+\.\d+' file

ou

grep -Eo "([0-9]{1,3}[\.]){3}[0-9]{1,3}" file
    
por αғsнιη 21.11.2014 / 15:42
1

Eu uso o grep:

echo 'This sentence contains an ip number 1.2.3.4 and port number 50, i want to print the IP address only.' | grep -oE '((1?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])\.){3}((1?[0-9]?[0-9]|2[0-4][0-9]|25[0-5]))'

Isso imprimirá apenas endereços IP válidos, ao contrário das outras respostas

    
por Jiří Gracík 26.11.2015 / 03:40
0

Eu faria assim no interpretador python 3. Ele não apenas pega o texto que está no formato 111.111.111.111 , mas também verifica se ele é válido ou não.

>>> import re
>>> import ipaddress
>>> text = "This sentence contains an ip number 1.2.3.4 and 111.111.111.111 451.976.897.786 port number 50, i want to print the IP address only."
>>> foo = re.findall(r'(?<!\S)(?:\d{1,3}\.){3}\d{1,3}(?!\S)', text)
>>> foo
['1.2.3.4', '111.111.111.111', '451.976.897.786']
>>> for i in foo:
...     try:
...         ipaddress.ip_address(i)
...     except:
...         pass
... 
IPv4Address('1.2.3.4')
IPv4Address('111.111.111.111')

Para obter o interpretador do python 3, digite o comando python3 no terminal.

    
por Avinash Raj 21.11.2014 / 16:59
0

Extensão para a resposta da choroba:

Se você não quiser que uma nova linha seja impressa e desejar apenas imprimir os IP's:

$ echo -e 'This sentence contains an ip number 1.2.3.4 and port number 50, \ni want to print the IP address only.\n One more IP is 1.24.53.3.' \
| sed -n 's/.*\([0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\).*//1p'

Saída:

1.2.3.4
1.24.53.3

Explicação:

-n flag is for quiet / silent.
 p print the replaced text
    
por snoop 26.11.2015 / 06:22
0

O AWK combinado com o RegExp é muito apropriado para o processamento de partes de linhas.

A idéia básica do one-liner abaixo é dar um loop por uma linha e verificar a presença de quatro dígitos e pontos, repetidos no máximo 4 vezes; ao mesmo tempo, podemos verificar um dígito repetido de 2 a 4 vezes para o número da porta

awk '{for(i=1;i<=NF;i++) { if ($i~/[[:digit:]\.]{4}/) printf $i; if ( $i~/[[:digit:]]{2,4}/) printf ":"$i  }}'

Execução de amostra

$ echo "This sentence contains an ip number 1.2.3.4 and port number 50, i want to print the IP address only." |  awk '{for(i=1;i<=NF;i++) { if ($i~/[[:digit:]\.]{4}/) printf $i; if ( $i~/[[:digit:]]{2,4}/) printf ":"$i  }}'

1.2.3.4:50,

Sua sentença contém 50 e, juntos, sem separação, portanto impressos juntos, mas com gsub(/[[:punct:]]/,"") que pode ser removido, se desejado.

    
por Sergiy Kolodyazhnyy 26.11.2015 / 08:34