Como filtrar endereços IPv4 e IPv6?

5
echo "1.1.1.1" | awk '/[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*/ {print $1}'

Como posso filtrar endereços IPv4 em um script e como filtrar endereços IPv6?

Eu quero dizer mais precisamente então isso para o oneliner só deve saída endereços IPv4 VÁLIDOS ou outro script para a saída apenas IPv6 addr VÁLIDO. Em diferentes idiomas? como: awk, perl?

ty!

    
por LanceBaynes 28.08.2011 / 19:13

4 respostas

4

Existem várias notações habituais para IPv4 e IPv6 . Aqui está uma expressão regular estendida, adequada para Perl m//x , que captura as notações usuais. Se você remover os comentários e os espaços em branco, poderá usá-lo com grep -E , awk ou qualquer outro utilitário que use expressões regulares estendidas (ERE).

^(
  ([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]|0+[0-3][0-7][0-7]|0x0*[0-9a-fA-F][0-9a-fA-F])
  (\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]|0+[0-3][0-7][0-7]|0x0*[0-9a-fA-F][0-9a-fA-F])){3}   # IPv4 dotted quad
| 0x[0-9a-fA-F]{1-8}             # IPv4 hexadecimal
| 0+[0-9]{0-10} | 0+[1-3]{11}    # IPv4 octal
| [1-9][0-9]{1-8}                # IPv4 decimal, small
| [1-3][0-9]{9}                  # IPv4 decimal, medium
| 4[0-9]{9}                      # IPv4 decimal, large (needs a further range check)
| [0-9a-fA-F]{1-4}(:[0-9a-fA-F]{1-4}){7}            # IPv6 with all groups
| ([0-9a-fA-F]{1-4}:){1-1}(:[0-9a-fA-F]{1-4}){1-6}  # IPv6 with 1-6 middle groups omitted
| ([0-9a-fA-F]{1-4}:){1-2}(:[0-9a-fA-F]{1-4}){1-5}  # IPv6 with 1-6 middle groups omitted
| ([0-9a-fA-F]{1-4}:){1-3}(:[0-9a-fA-F]{1-4}){1-4}  # IPv6 with 1-6 middle groups omitted
| ([0-9a-fA-F]{1-4}:){1-4}(:[0-9a-fA-F]{1-4}){1-3}  # IPv6 with 1-6 middle groups omitted
| ([0-9a-fA-F]{1-4}:){1-5}(:[0-9a-fA-F]{1-4}){1-2}  # IPv6 with 1-6 middle groups omitted
| ([0-9a-fA-F]{1-4}:){1-6}(:[0-9a-fA-F]{1-4}){1-1}  # IPv6 with 1-6 middle groups omitted
)$

No caso de um valor decimal, você precisa de uma outra verificação de intervalo (você pode fazer um regexp dele, mas seria grande):

if (!/[^0-9]/ && /^[^0]/) { # if it's a decimal number
    die if $_ > 4294967295 # reject numbers above 2^32-1
}

Se a ferramenta que você usa só suporta números de 32 bits, você pode fazer o teste somente se o número começar com 4, e tira o 4 antes de fazer a verificação.

if (!/[^0-9]/ && /^4/) { # if it's a decimal number beginning with 4
    my $tmp = $_;
    $tmp =~ s/^4//;
    die if $tmp > 294967295;
}
    
por 28.08.2011 / 20:34
0

No bash:

validIP4 () 
{ 
    IFS='.' read na nb nc nd;
    for n in "$na" "$nb" "$nc" "$nd";
    do
        [[ ${#n} -le 3 ]] && [[ "${n//[^0-9]/}" = "$n" ]] && [[ $n -lt 256 ]] || return 1;
    done
    echo OK
}

Exemplos de uso:

  • echo 142.24.045.33 | validIP4
  • echo sd3.3.4.6 | validIP4 || echo "nope :("
  • echo 342.0.0.2 | validIP4 || echo "Noo...."
  • echo 3.2.1.0 | validIP4 && echo "Yes, sir."

Como Gilles observou, isso verifica apenas a notação decimal ponto-mais popular de um endereço IPv4.

O IPv6 pode ser feito de maneira similar, mas precisa de muito mais checagem, porque (1) ele usa hexa e (2) algumas seções de zeros completos podem ser totalmente omitidas.

    
por 28.08.2011 / 20:08
0

Primeiro, testes:

IPv4 0.0.0.0 # Standard IP
IPv4 1.2.3.4 # Standard IP
IPv4 255.255.255.255 # Standard IP
IPv4 8.08.008.0008 # Should not treat leading zero as octal
IPv4 1.1.1 || true # Too short
IPv4 1.1.1.1.1 || true # Too long
IPv4 a.b.c.d || true # Non-numeric
IPv4 0.0.0.-1 || true # Negative

Qualquer coisa entre 0.0.0.0 e 255.255.255.255 no shell:

IPv4() {
    quads=0
    while IFS= read -r quad
    do
        let quads++
        while [[ $quad = 0* ]]
        do
            quad=${quad#0}
        done
        if [[ $quads -gt 4 || ! "${quad:-0}" =~ [0-9]+ || "${quad:-0}" -lt 0 || "${quad:-0}" -gt 255 ]]
        then
            return 1
        fi
    done < <(echo "$1" | tr '.' '\n')
    if [[ ! $quads -eq 4 ]]
    then
        return 1
    fi
}
    
por 28.09.2011 / 10:10
0

Estendendo a resposta do Gilles, sua expressão regular não funciona no ActiveState Perl (versão 5.20.3, Windows 7/64). Segundo aqui , os quantificadores para os padrões de {num1-num2} precisam ser alterados para {num1,num2} e vai funcionar.

Obrigado pelo REGEXP, ele me poupa para adicionar o módulo Data::Validate::IP no meu site Perl.

    
por 17.01.2018 / 23:33

Tags