Endereço IP ou não?


25

Sua ferramenta de digitalização em rede é irritantemente exigente quanto à entrada e falha imediatamente se você fornecer um endereço IPv4 que contenha caracteres incorretos ou não esteja formatado corretamente.

Um endereço IPv4 é um endereço numérico de 32 bits escrito como quatro números separados por pontos. Cada número pode ser de zero a 255 .

Precisamos escrever uma ferramenta para pré-validar a entrada para evitar essas falhas, e nossa ferramenta específica é exigente: Um formato válido será semelhante a a.b.c.donde a, b, c e d:

  • Pode ser um 0número natural ou sem zeros à esquerda .
  • Deve estar entre 0 e 255 (inclusive).
  • Caso não contêm símbolos especiais, como +, -, ,e outros.
  • Deve ser decimal (base 10)

Entrada : uma sequência

Saída : valor Truthy ou Falsey (valores arbitrários também aceitos)

Casos de teste :

Input            |  Output  |  Reason
                 |          |
- 1.160.10.240   |  true    |
- 192.001.32.47  |  false   |  (leading zeros present)
- 1.2.3.         |  false   |  (only three digits)
- 1.2.3          |  false   |  (only three digits)
- 0.00.10.255    |  false   |  (leading zeros present)
- 1.2.$.4        |  false   |  (only three digits and a special symbol present)
- 255.160.0.34   |  true    |
- .1.1.1         |  false   |  (only three digits)
- 1..1.1.1       |  false   |  (more than three periods)
- 1.1.1.-0       |  false   |  (special symbol present)
- .1.1.+1        |  false   |  (special symbol present)
- 1 1 1 1        |  false   |  (no periods)
- 1              |  false   |  (only one digit)
- 10.300.4.0     |  false   |  (value over 255)
- 10.4F.10.99    |  false   |  (invalid characters)
- fruit loops    |  false   |  (umm...)
- 1.2.3.4.5      |  false   |  (too many periods/numbers)
- 0.0.0.0        |  true    |
- 0.0 0.0.       |  false   |  (periods misplaced)
- 1.23..4        |  false   |  (a typo of 1.2.3.4)
- 1:1:1:1:1:1:1:1|  false   |  (an IPv6 address, not IPv4)

Isso é , e o menor número de bytes vencerá!

Nota para os usuários - se você quiser adicionar mais casos de teste, será bem-vindo (sugerindo uma edição). Mas, certifique-se de que os casos de teste não se repitam! obrigado


10
Sugerir testcases: 1.1.1.1.1, 1.1.1.1., .1.1.1, 1..1.1, 1..1.1.1, 1.1.1.0, 1.1.1.-0, 1.1.1.+1, 1.1.1.1E1, 1.1.1.256, 1.1.1.0x1, 255.255.255.255, 0.0.0.0, 'or 1=1--, <empty string>, 1 1 1 1, 1,1,1,1.
tsh

5
Sugira a adição de casos de teste "1.2.3.4.5" (para descartar IPs muito longos) e "999.0.0.0" (para descartar IPs muito grandes).
Triggernometry

5
Possivelmente um pouco exigente, mas você provavelmente deve se referir a "endereços IPv4" em vez de "endereços IP" - ou pelo menos mencionar em algum lugar que você apenas quer dizer endereços IPv4 - caso contrário, 1234: 5678 :: 1 deve ser um endereço IP válido (enquanto a partir da descrição é claro que isso não é destinado :)
psmears

3
@Criggie A premissa não é realmente verificar todas as regras IP4 reais (como as que você mencionou), é para garantir que a string de entrada não trava em outro aplicativo (presumivelmente mal escrito) que permite apenas a entrada de uma forma muito específica . Além disso, não vamos mudar as regras de um desafio que já tem mais de 30 respostas.
#

2
@Criggie Vale notar que a RFC declara que "os endereços têm um comprimento fixo de quatro octetos". Acho que os casos adicionais que você está referenciando são mais especializados que esse desafio.
puxão

Respostas:


26

Código da máquina X86_64: 18 16 bytes

Edit: Esta resposta não funciona muito bem, pois

  1. Estou usando inet_ptonas bibliotecas C padrão, o que significa que preciso do externo. Eu não incluí o extern na minha contagem de bytes.
  2. Como resultado, usei a zona vermelha para o endereço real, mas chamei uma função que também poderia ter usado a zona vermelha. Felizmente, ele não está na minha máquina, mas alguma compilação de biblioteca padrão estranha pode usá-la, o que pode causar um comportamento indefinido.

E sim, tudo está sendo feito por uma função já escrita

Enfim, é isso que eu tenho: 48 89 fe 6a 02 5f 48 8d 54 24 80 e9 00 00 00 00

Montagem:

section .text
    extern inet_pton
    global ipIsValid

ipIsValid:
    mov rsi, rdi
    ;mov rdi, 2 ; change to 10 for ipv6
    push 2
    pop rdi ; thank you peter
    lea rdx, [rsp - 128]
    jmp inet_pton

Explicação:

Dê uma olhada inet_pton(3). Ele pega um endereço IP de string e o coloca em um buffer que você pode usar struct sockaddr. São necessários três argumentos: a família de endereços ( AF_INET(ipv4), 2 ou AF_INET6(ipv6), 10), a cadeia de caracteres do endereço IP e um ponteiro para a saída. Retorna 1 em caso de sucesso, 0 para um endereço inválido ou -1 para quando a família de endereços não é nem AF_INETou AF_INET6(o que nunca ocorrerá porque estou passando uma constante para ele).

Então, eu simplesmente movo a string para o registrador do segundo argumento, defino o primeiro registrador como 2 e o terceiro para a zona vermelha (128 bytes abaixo do ponteiro da pilha), pois não me importo com o resultado. Então eu posso simplesmente jmppara inet_ptone deixe que o retorno direto para o chamador!

Eu desenvolvi este programa de teste rápido para testar seus casos:

#include <stdio.h>
#include <arpa/inet.h>
#include <netinet/ip.h>

extern int ipIsValid(char *);

int main(){
    char *addresses[] = {
        "1.160.10.240",
        "192.001.32.47",
        "1.2.3.",
        "1.2.3",
        "0.00.10.255",
        "1.2.$.4",
        "255.160.0.34",
        ".1.1.1",
        "1..1.1.1",
        "1.1.1.-0",
        ".1.1.+1",
        "1 1 1 1",
        "1",
        "10.300.4.0",
        "10.4F.10.99",
        "fruit loops",
        "1.2.3.4.5",
        NULL
    };

    for(size_t i = 0; addresses[i] != NULL; ++i){
        printf("Address %s:\t%s\n", addresses[i],
            ipIsValid(addresses[i]) ? "true" : "false");
    }
    return 0;
}

Monte com nasm -felf64 assembly.asm, compile com gcc -no-pie test.c assembly.oe você obterá:

Address 1.160.10.240:   true
Address 192.001.32.47:  false
Address 1.2.3.: false
Address 1.2.3:  false
Address 0.00.10.255:    false
Address 1.2.$.4:    false
Address 255.160.0.34:   true
Address .1.1.1: false
Address 1..1.1.1:   false
Address 1.1.1.-0:   false
Address .1.1.+1:    false
Address 1 1 1 1:    false
Address 1:  false
Address 10.300.4.0: false
Address 10.4F.10.99:    false
Address fruit loops:    false
Address 1.2.3.4.5:  false

Eu poderia fazer isso muito menor se o chamador passasse AF_INETou AF_INET6para a função


4
Eu amo que você fez isso em asm. E o fato de você explicá-lo para aqueles que podem não entender (assim como o código de teste) é ainda melhor. O que não quer dizer que eu poderia ter feito o mesmo; já se passaram muitos anos, mas lembro-me o suficiente para ver exatamente o que sua explicação (e, portanto, o processo) está dizendo (faz). Bom trabalho.
Pryftan #

4
e9 00 00 00 00é um jmp near $+5, não um jmp inet_pton. Se você fornecer código de operação, você deve incluir o incluindo inet_ptonparte, não deixar um espaço em branco
l4m2

1

3
inclua o externo no título da resposta, pois o programa exige e ele não está disponível em todas as plataformas.
Qd #

1
o "mov rdi, 2" pode ser "push 2 / pop rdi" por -2 bytes. Observe também que a desmontagem está errada ou o código está errado. É "mov edi" (não rdi) ou há um prefixo ausente.
peter ferrie

13

Java (JDK) , 63 bytes

s->("."+s).matches("(\\.(25[0-5]|(2[0-4]|1\\d|[1-9])?\\d)){4}")

Experimente online!

Créditos


Você esqueceu de remover o ponto e vírgula à direita. ;) E posso verificar se funciona para todos os casos de teste, incluindo aqueles nos comentários. Vou ver se eu vejo algumas coisas para jogar golfe.
Kevin Cruijssen 22/10

3
Falha ao ligar.1.2.3.4
l4m2 22/10/1918

É permitido usar booleano quando explicitamente exigir 0/1?
L4m2 22/10/19

1
@ l4m2 A pergunta original era Válida / Inválida. Portanto, presumo que qualquer valor de verdade / falsey seja aceitável aqui.
Kevin Cruijssen 22/10

Output: 0 or 1e Java não tem bool- auto> int
l4m2

12

JavaScript (Node.js) , 43 bytes

x=>x.split`.`.map(t=>[t&255]==t&&[])==`,,,`

Experimente online!

JavaScript (Node.js) , 46 bytes

x=>x.split`.`.every(t=>k--&&[t&255]==t,k=4)*!k

Experimente online!

parte usada de Arnauld

JavaScript (Node.js) , 54 53 51 bytes

x=>x.split`.`.every(t=>k--*0+t<256&[~~t]==t,k=4)*!k

Experimente online!

-2B para 0+t<256, -1B de Patrick Stephansen, + 1B para evitar entrada1.1.1.1e-80

Solução RegExp 58 54 bytes

s=>/^((2(?!5?[6-9])|1|(?!0\d))\d\d?\.?\b){4}$/.test(s)

Obrigado Deadcode por 3 bytes


Eu adicionei alguns casos de teste!
RV7


1
@KevinCruijssen 0.0.0.0é aqui um verdadeiro. Por que a injeção de SQL está aqui?
L4m2 22/10

Ah, espere, eu interpreto mal a frase na descrição do desafio. 0.0.0.0é realmente verdade. Que o golfe vontade minha resposta, bem .. (? E o que você quer dizer com injeção de SQL: S O link é TIO com casos de teste TODOS.)
Kevin Cruijssen

1
@ l4m2 Eu adicionei, já que precisamos de alguns casos de teste que nem parecem um endereço IP.
Tsh #

11

PHP , 39 36 bytes

<?=+!!filter_var($argv[1],275,5**9);

Experimente online!

275 se assemelha à constante FILTER_VALIDATE_IP

5 ** 9 está sendo usado em vez da constante FILTER_FLAG_IPV4. Isso é suficiente, porque 5**9 & FILTER_FLAG_IPV4é verdade, que é exatamente o que o PHP faz em segundo plano, como Benoit Esnard apontou.

Aqui, filter_varretorna o primeiro argumento, se for um endereço IPv4 válido, ou falso, se não for. Com +!!, produzimos a saída exigida pelo desafio.


3
Usar em 5**9vez de 1048576salvar 3 bytes aqui: o PHP usa &para testar os sinalizadores IPv4 / IPv6 , portanto, qualquer número entre 1048576 e 2097151 é válido.
Benoit Esnard

Declaro, por meio deste documento, sua resposta por ser (basicamente) minha resposta: codegolf.stackexchange.com/a/174470/14732, que foi escrita em 22/10/2018 09: 17: 34UTC enquanto a sua foi escrita em 22/10/2018 09: 21: 55UTC. Mesmo se eu reverter a otimização de 1 byte fornecida pelo @BenoitEsnard, minha resposta é exatamente igual à sua em funcionalidade.
Ismael Miguel

2
Preciso me desculpar, não vi sua resposta, embora, no momento em que a compusesse, não houvesse submissão em PHP sobre essa questão (como você disse, a diferença de horário é inferior a cinco minutos).
Oktupol

Eu sei e entendo. Eu só notei a sua agora. Eu posso reverter o meu e você mantém a otimização. Mas não sei se isso faz com que a resposta seja diferente o suficiente uma da outra.
Ismael Miguel

17
@IsmaelMiguel Eu não votaria em alguém por isso se for plausível que o seu não estivesse lá quando eles começaram. Com uma diferença de 5 minutos, não só é plausível, é quase certamente o caso, o que é aparente mesmo sem o autor dizer isso.
Duncan X Simpson

11

PHP, 36 bytes

echo(ip2long($argv[1])===false?0:1);

ip2longé um conhecido embutido função .



Isso parece usar recursos não documentados presentes em versões mais recentes (presumo que seja do PHP7 +). Lembre-se de que, para PHP 4 e 5, isso aceita IPs incompletos.
Ismael Miguel



1
Isso dará sucesso se você alimentar qualquer número inteiro, como 1, 2, etc. Não pense que deveria. E também se você alimentá-lo com algo como 100.100.100
nl-x

10

Perl 6 , 22 21 20 bytes

-1 byte graças a Phil H.

{?/^@(^256)**4%\.$/}

Experimente online!

Explicação

{                  }  # Anonymous Block
  /               /   # Regex match
   ^             $    # Anchor to start/end
    @(    )           # Interpolate
      ^256            #   range 0..255,
                      #   effectively like (0|1|2|...|255)
           **4        # Repeated four times
              %\.     # Separated by dot
 ?                    # Convert match result to Bool

3
Cara, preciso gastar mais tempo descobrindo as expressões regulares do Perl 6. Eu também não tinha o %modificador. Gostaria de saber se ele tenta verificar todas as 256**4possibilidades?
Jo rei

1
Em vez de <{^256}>você pode simplesmente converter o intervalo em uma matriz @(^256)para -1 char TIO . Ao alterar o bloco de código para uma matriz, ele também fica muito mais rápido (0,4s em vez de> 30).
Phil H

@ Philh Legal, obrigado. Eu tentei, $(^256)mas agora percebo por que isso não funcionou.
Nwellnhof 25/10/19

9

05AB1E , 26 24 23 22 23 bytes

'.¡©g4Q₅Ý®å`®1šDïþJsJQP

-1 byte graças a @Emigna .
+1 byte para correção de erros de caso de teste 1.1.1.1E1retornando incorretamente um resultado verdadeiro.

Experimente online ou verifique todos os casos de teste .

Explicação:

'.¡              '# Split the (implicit) input by "."
   ©              # Save it in the register (without popping)
    g4Q           # Check that there are exactly 4 numbers
    ₅Ý®å          # Check for each of the numbers that they are in the range [0,255],
        `         # and push the result for each number separated onto the stack
    ®1šDïþJsJQ    # Check that each number does NOT start with a "0" (excluding 0s itself),
                  # and that they consist of digits only
              P   # Check if all values on the stack are truthy (and output implicitly)

1
Você deve ser capaz de usar em Āvez de<d
Emigna 22/10

@MagicOctopusUrn Receio que não para 1.1.1.1E1, 1..1.1.1, 1.1.1.1., 192.00.0.255, e 0.00.10.255. : (PS Eu fixou o 1.1.1.1E1adicionando o þao juntar-and-igual cheque.)
Kevin Cruijssen

Justo, imaginei que perdi alguma coisa.
Magic Octopus Urn

@MagicOctopusUrn A questão principal é 05AB1E, vendo números com 0 iniciais iguais aos sem, mesmo como string. É por isso que eu uso o DïþJsJQcheque onde ïlançá-lo para int para remover 0s principais, e þsó deixa dígitos remover coisas como E, -, etc. :) A é para o caso de teste 0.00.10.255, uma vez 00010255e 0010255seriam iguais.
Kevin Cruijssen 22/10

Sim, eu passei pelo mesmo absurdo, a reversão de todos os números funcionou muito bem, exceto nesses casos. Interessante quando recursos benéficos para alguns problemas se tornam quase parecidos com bugs para outros.
Magic Octopus Urn

6

PowerShell, 59 51 49 bytes

-8 bytes, obrigado @AdmBorkBork

-2 bytes, trueou falsepermitido pelo autor

try{"$args"-eq[IPAddress]::Parse($args)}catch{!1}

Script de teste:

$f = {

try{"$args"-eq[IPAddress]::Parse($args)}catch{!1}

}

@(
    ,("1.160.10.240" , $true)
    ,("192.001.32.47" , $false)
    ,("1.2.3." , $false)
    ,("1.2.3" , $false)
    ,("0.00.10.255" , $false)
    ,("192.168.1.1" , $true)
    ,("1.2.$.4" , $false)
    ,("255.160.0.34" , $true)
    ,(".1.1.1" , $false)
    ,("1..1.1.1" , $false)
    ,("1.1.1.-0" , $false)
    ,("1.1.1.+1" , $false)
    ,("1 1 1 1" , $false)
    ,("1"            ,$false)
    ,("10.300.4.0"   ,$false)
    ,("10.4F.10.99"  ,$false)
    ,("fruit loops"  ,$false)
    ,("1.2.3.4.5"    ,$false)

) | % {
    $s,$expected = $_
    $result = &$f $s
    "$($result-eq$expected): $result : $s"
}

Saída:

True: True : 1.160.10.240
True: False : 192.001.32.47
True: False : 1.2.3.
True: False : 1.2.3
True: False : 0.00.10.255
True: True : 192.168.1.1
True: False : 1.2.$.4
True: True : 255.160.0.34
True: False : .1.1.1
True: False : 1..1.1.1
True: False : 1.1.1.-0
True: False : 1.1.1.+1
True: False : 1 1 1 1
True: False : 1
True: False : 10.300.4.0
True: False : 10.4F.10.99
True: False : fruit loops
True: False : 1.2.3.4.5

Explicação:

O script tenta analisar uma sequência de argumentos, para construir um objeto .NET, IPAddress .

  • return $truese objectcriado e a sequência de argumentos é igual a uma representação de sequência do object(endereço normalizado por object.toString())
  • retornar $falsecaso contrário

PowerShell, 59 56 54 bytes, 'não use uma lib .NET'

-3 bytes, trueou falsepermitido pelo autor

-2 bytes, graças a @ Deadcode pelo regexp legal.

".$args"-match'^(\.(2(?!5?[6-9])|1|(?!0\B))\d\d?){4}$'

Experimente online!

Obrigado @ Olivier Grégoire pela expressão regular original.


1
Você não precisa ligar, |% t*gpois o PowerShell converterá automaticamente o lado direito -eqcomo uma sequência, porque o lado esquerdo é uma sequência. -try{+("$args"-eq[IPAddress]::Parse($args))}catch{0}
AdmBorkBork

Você pode gravar 2 bytes da versão "não use uma biblioteca .NET" usando meu regex (adaptado ao truque de inserir um período, que obviamente não pode estar na minha versão porque é um regex puro): tio.run/…
Deadcode

5

C (gcc) / POSIX, 26 bytes

f(s){s=inet_pton(2,s,&s);}

Experimente online!

Funciona como código de 64 bits no TIO, mas provavelmente exige isso sizeof(int) == sizeof(char*)em outras plataformas.


@TobySpeight Sim, se você estiver no x86, provavelmente deverá tentar no modo de 32 bits ( -m32).
Nwellnhof 22/10

Eu fiz funcionar, passando scomo um char*(sem acesso a um sistema ILP32 aqui), e sim, eu estava me misturando inet_aton().
Toby Speight

5

PHP 7+, 37. 35 32 bytes

Isso usa a função interna filter_varpara validar que é um endereço IPv4 .

Para que funcione, você precisa passar a chave isobre uma solicitação GET.

<?=filter_var($_GET[i],275,5**9);

Não produzirá nada (para um falsyresultado) ou o IP (para um truthyresultado), dependendo do resultado.

Você pode tentar isso em: http://sandbox.onlinephpfunctions.com/code/639c22281ea3ba753cf7431281486d8e6e66f68e http://sandbox.onlinephpfunctions.com/code/ff6aaeb2b2d0e0ac43f48125de0549320bc071b4


Isso usa os seguintes valores diretamente:

  • 275 = FILTER_VALIDATE_IP
  • 1 << 20 = 1048576 = FILTER_FLAG_IPV4
  • 5 ** 9 = 1953125 (que tem o bit necessário como "1", para 1048576)

Obrigado a Benoit Esnard por esta dica que me salvou 1 byte!

Obrigado a Titus por me lembrar das mudanças no desafio.


Eu olhei para usar a função ip2long, mas funciona com endereços IP não completos.

Endereços IPv4 não completos são considerados inválidos neste desafio.

Se eles fossem permitidos, este seria o código final (apenas para o PHP 5.2.10):

<?=ip2long($_GET[i]);

Atualmente, não está explícito na documentação que isso parará de funcionar (quando passou um ip incompleto) com as versões mais recentes do PHP.

Após o teste, confirmou que era esse o caso.

Obrigado ao nwellnhof pela dica!


Using 5**9 instead of 1<<20 saves one byte here: PHP uses & to test the IPv4 / IPv6 flags, so any number between 1048576 and 2097151 is valid.
Benoit Esnard

In newer PHP versions, ip2long doesn't allow incomplete addresses.
nwellnhof

@BenoitEsnard Thank you! I've added it to the answer
Ismael Miguel

@nwellnhof After testing, I confirm that that is the case. However, I don't think it is a good idea to use it, since it isn't explicitly documented.
Ismael Miguel

+!! is not required; the OP now accepts arbitrary truthy values.
Titus

5

Python 3: 81 78 70 69 66 bytes

['%d.%d.%d.%d'%(*x.to_bytes(4,'big'),)for x in range(16**8)].count

Loop over all possible IPv4 addresses, get the string representation and compare it to the input. It uh... takes a while to run.

EDIT: Removed 3 bytes by switching from full program to anonymous function.

EDIT2: Removed 8 bytes with help from xnor

EDIT3: Removed 1 byte by using an unpacked map instead of list comprehension

EDIT4: Removed 3 bytes by using list comprehension instead of the ipaddress module


2
I think your anonymous function can just be [str(ip_address(x))for x in range(256**4)].count. Also, 256**4 can be 16**8.
xnor

5

C# (Visual C# Interactive Compiler), 84 79 65 bytes

s=>s.Split('.').Sum(t=>byte.TryParse(t,out var b)&t==b+""?1:5)==4

Try it online!

-5 and -14 bytes saved thanks to @dana!

# C# (Visual C# Interactive Compiler), 61 bytes

s=>s.Count(c=>c==46)==3&IPAddress.TryParse(s,out IPAddress i)

Try it online!

This is a work in progress. The code use System.Net (+17 bytes if you count it). if you wonder why I count and parse:

The limitation with IPAddress.TryParse method is that it verifies if a string could be converted to IP address, thus if it is supplied with a string value like "5", it consider it as "0.0.0.5".

source

As @milk said in comment, it will indeed fail on leading zeroes. So, the 61 bytes one is not working.


1
@dana great. Nicely done! Four more and it will beat the 61 bytes solutions!
aloisdg says Reinstate Monica

4

Python 2, 85 82 81 bytes

-1 byte thanks to Kevin Cruijssen

from ipaddress import*
I=input()
try:r=I==str(IPv4Address(I))
except:r=0
print~~r

Try it online!

113 byte answer is deleted as it fails for 1.1.1.1e-80


1
You can golf print 1*r to print~~r. +1 though, since it seem to work for all possible test cases suggested thus far. PS: Your 113 byte answer fails for 1.1.1.1e-80.
Kevin Cruijssen

@KevinCruijssen Thanks! Didn't think about such notation of numbers
Dead Possum

Isn't ipaddress a Python 3 module?
Farhan.K

@Farhan.K Dunno, but it works in TIO
Dead Possum

4

Japt, 17 15 bytes

q.
ʶ4«Uk#ÿòs)Ê

Try it or run all test cases or verify additional test cases from challenge comments


Explanation

We split to an array on ., check that the length of that array is equal to 4 AND that the length when all elements in the range ["0","255"] are removed from it is falsey (0).

                 :Implicit input of string U
q.               :Split on "."
\n               :Reassign resulting array to U
Ê                :Length of U
 ¶4              :Equals 4?
   «             :&&!
    Uk           :Remove from U
      #ÿ         :  255
        ò        :  Range [0,255]
         s       :  Convert each to a string
          )      :End removal
           Ê     :Length of resulting array

Nice answer. Also verified for all suggested test cases thus far. Curious to see that explanation.
Kevin Cruijssen

2
@KevinCruijssen, explanation added. Thanks for those additional test cases.
Shaggy

3

Mathematica, 39 31 bytes

Original version:

¬FailureQ[Interpreter["IPAddress"][#]]&

Modified version (thanks to Misha Lavrov)

 AtomQ@*Interpreter["IPAddress"]

which returns True if the input is a valid IP address (try it).

In case you insist on getting 1 and 0 instead, then an additional 7 bytes would be necessary:

Boole/@AtomQ@*Interpreter["IPAddress"]

Since Interpreter["IPAddress"] returns a string for valid input, and some complicated failure object for invalid input, we can test for valid inputs with AtomQ[Interpreter["IPAddress"][#]]&, which can be further shortened to the function composition AtomQ@*Interpreter["IPAddress"]. Try it online!
Misha Lavrov

Fails on an IPv6 address like 2001:0db8:85a3:0000:0000:8a2e:0370:7334.
lirtosiast


3

Python 2, 93 89 67 53 bytes

[i==`int(i)&255`for i in input().split('.')]!=[1]*4>_

Try it online!

Thanks to Dennis for shaving another 14 bytes on the internal comparisons and exit code.

Special thanks to Jonathan Allan for shaving 22 bytes & a logic fix! Pesky try/except begone!

Taking properly formatted strings instead of raw bytes shaves off 4 bytes, thanks Jo King.


Your check can be golfed to i==`int(i)&255` . Also, you can force an error with [...]!=[1]*4>_, since you're using exit codes anyway. Try it online!
Dennis

@Dennis I don't understand what >_ does. The bitwise and is quite ingenious though... I was unsuccessful in combining those myself.
TemporalWolf

2
If the != returns False, Python short-circuits and nothing happens; the interpreter exits normally. If it returns True, >_ raises a NameError, because the variable _ is undefined.
Dennis

Figures I chain comparisons in my answer and then miss the obvious result in your comment. Thanks for the explanation.
TemporalWolf

3

sfk, 176 bytes

* was originally Bash + SFK but TIO has since added a proper SFK wrapper

xex -i "_[lstart][1.3 digits].[1.3 digits].[1.3 digits].[1.3 digits][lend]_[part2]\n[part4]\n[part6]\n[part8]_" +xed _[lstart]0[digit]_999_ +hex +linelen +filt -+1 -+2 +linelen

Try it online!


Would first checking the error printout from nc [addr] 1 -w1 shorten this?

@Rogem nc accepts leading zeroes as well as IPv6 addresses, so I'd still have to handle those - and this is intended more as a sfk answer than a shell answer anyway.
Οurous

3

Python3 Bash* 60

*Also other shells. Any one for which the truthy/falsy test passes on a program exit code

read I
python3 -c "from ipaddress import*;IPv4Address('$I')"

Explanation

The trouble with a pure Python solutions is that a program crashing is considered indeterminate. We could use a "lot" of code to convert an exception into a proper truthy/fasly value. However, at some point the Python interpreter handles this uncaught exception and returns a non-zero exit code. For the low-low cost of changing languages to your favourite Unix shell, we can save quite a bit of code!

Of course, this is vulnerable to injection attacks... Inputs such as 1.1.1.1'); print('Doing Something Evil are an unmitigated threat!


(Explanation it is (not Explaination).)
Peter Mortensen

@PeterMortensen Yikes. It was even underlined in red. My browser tried to save me, but I wouldn't listen. Thanks for catching that!
Sompom

Full programs are allowed to output via exit codes, therefore this could be 43 bytes.
ბიმო

@BMO Interesting. Thanks for pointing that out! I think the problem definiiton changed from "Truthy/Falsy" to also allowing arbitrary output since I posted this, but I could have just not noticed before :)
Sompom

3

ECMAScript pure regex, 41 bytes

^((2(?!5?[6-9])|1|(?!0\B))\d\d?\.?\b){4}$

Try it online!
Try it on regex101

I think the logic in this regex speaks for itself, so I will merely pretty-print but not comment it:

^
(
    (
        2(?!5?[6-9])
    |
        1
    |
        (?!0\B)
    )
    \d\d?
    \.?\b
){4}
$

This can be used to shave 2 bytes off the following other answers:

Here is an alternative version that allows leading zeros, but does so consistently (octets may be represented by a maximum of 3 decimal digits):

^((2(?!5?[6-9])|1|0?)\d\d?\.?\b){4}$

Or allow any number of leading zeros:

^(0*(2(?!5?[6-9])|1?)\d\d?\.?\b){4}$


1
\b and \B... it's smart!
mazzy

1
@mazzy Yes, those two really come in handy! I could've used (?!0\d) instead, but I like \B better!
Deadcode

The powershell answer doesn't get shorter with your regexp. I'm sorry. Quotes are needed to convert an array to a string. Try it online!
mazzy

1
The \.?\b saved me a byte on my answer too, thanks!
Neil

1
Saved 3 bytes thx
l4m2

2

Red, 106 bytes

func[s][if error? try[t: load s][return off]if 4 <> length? t[return off]s =
form as-ipv4 t/1 t/2 t/3 t/4]

Try it online!

Returnd true or false

Explanation:

f: func [ s ] [
    if error? try [                  ; checks if the execution of the next block result in an error
        t: load s                    ; loading a string separated by '.' gives a tuple   
    ] [                              ; each part of which must be in the range 0..255
        return off                   ; if there's an error, return 'false' 
    ]
    if 4 <> length? t [              ; if the tuple doesn't have exactly 4 parts
        return off                   ; return 'false'  
    ]
    s = form as-ipv4 t/1 t/2 t/3 t/4 ; is the input equal to its parts converted to an IP adress
]

2

Stax, 14 bytes

∞n·Θ3ª&JH‼∙*~Γ

Run and debug it

Unpacked, ungolfed, and commented, it looks like this.

VB      constant 256
r       [0 .. 255]
'|*     coerce and string-join with "|"; i.e. "0|1|2|3 ... 254|255"
:{      parenthesize to "(0|1|2|3 ... 254|255)"
]4*     make 4-length array of number pattern
.\.*    string join with "\\."; this forms the complete regex
|Q      is the input a complete match for the regex?

Run this one


Surprised to know that you made the language Stax! it is working well.
rv7

Thanks! The space of golfing languages is surprisingly crowded, and I'm not sure if stax can justify its own existence on its merits, but my main goal was just to see if I could do it and maybe learn something. It ended up being more fun than expected.
recursive

2

Python 3, 109 93 bytes

import re
lambda x:bool(re.match(r'^((25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(\.(?!$)|$)){4}$',x))

Explanation

Each octet can be 0 - 255 :

  • starts with 25 and having 0-5 as last digit
  • start with 2, has 0-4 as second digit and any digit at the end
  • starts with 1, and 00 - 99 as rest digits
  • has only 2 digits - 1-9 being the first one and any digit thereafter
  • or just a single digit

An octet can end with a (.) or just end, with the condition that it cannot do both , the negative lookahead (?!$) takes care of this case

Thanks @Zachary for making me realize I can discard spaces (since it is code golf)
Thanks @DLosc for the improvements and making me realize my mistake, its been corrected now.


2
Some explanation for this might help.
Nissa

x: re.match=>x:re.match; , x => ,x, and ) is => )is should save 3 bytes. Also, in the regex, you can use \d for each occurrence of [0-9], and [1]=>1. This seems like a great first post, though!
Zacharý

[1-9][0-9]|[0-9] can become [1-9]\d|\d (per Zacharý's advice), which can become [1-9]?\d. Also, instead of testing re.match(...)is not None, you can do bool(re.match(...)) since match objects are truthy and None is falsey. :)
DLosc

Hmm. Actually, this fails on the test case 1.2.3.4.5 (and also 1.2.3.4., which isn't in the official list of test cases), because it can match a period instead of end-of-string after the fourth number.
DLosc


2

Charcoal, 45 21 bytes

I∧⁼№θ.³¬Φ⪪θ.¬№E²⁵⁶Iλι

Try it online! Link is to verbose version of code. Edit: Saved 24 bytes by porting @Shaggy's Japt answer. Explanation:

    θ                   Input string
   №                    Count occurrences of
     .                  Literal `.`
  ⁼                     Equal to
      ³                 Literal 3
 ∧                      Logical And
       ¬                Logical Not
          θ             Input string
         ⪪              Split on
           .            Literal `.`
        Φ               Filter by
            ¬           Logical Not
               ²⁵⁶      Literal 256
              E         Map over implicit range
                   λ    Map value
                  I     Cast to string
             №          Count occurrences of
                    ι   Filter value
I                       Cast to string
                        Implicitly print

Fails for test cases with negative integers like 123.-50.0.12 or 1.1.1.-80. Everything else seems to work fine. So the <256 check should be in [0,255] instead.
Kevin Cruijssen

@KevinCruijssen Actually the code to filter out invalid characters wasn't working because I forgot to change the variable in the inner loop. Should be fixed now.
Neil

2

Retina, 46 44 bytes

^
.
^(\.(25[0-5]|(2[0-4]|1\d|[1-9])?\d)){4}$

Port of @OlivierGrégoire's Java answer, so make sure to upvote him!
-2 bytes thanks to @Neil.

Try it online.

Explanation:

^
.                           # Prepend a dot "." before the (implicit) input
^...$                       # Check if the entire string matches the following regex
                            # exactly, resulting in 1/0 as truthy/falsey:
 (                          #  Open a capture group
  \.                        #   A dot "."
    (25[0-5]                #   Followed by a number in the range [250,255]
    |(2[0-4]|         ) \d) #   or by a number in the range [200,249]
    |(      |1\d|     ) \d) #   or by a number in the range [100,199]
    |(          |[1-9]) \d) #   or by a number in the range [10,99]
    |(                )?\d) #   or by a number in the range [0,9]
 )                          #  Close capture group
  {4}                       #  This capture group should match 4 times after each other

My attempt (which I didn't post because the question got put on hold at the time) was the same length, but didn't have the \d group optimisation, so you can save two bytes because you don't need the M specification on the last line.
Neil

I managed to get Retina down to 42 bytes by porting the Perl 6 answer but this answer also works in 0.8.2 which my port doesn't.
Neil

2

Jelly, 11 bytes

⁹ḶṾ€ṗ4j€”.ċ

A monadic link accepting a list of characters which yields 1 if it's a valid address and 0 otherwise. Builds a list of all 2564=4294967296 addresses and then counts the number of occurrences of the input therein.

Here's similar @ Try it online! that uses 16 () rather than 256 (), since the method is so inefficient!

How?

⁹ḶṾ€ṗ4j€”.ċ - Link: list of characters, S
⁹           - literal 256
 Ḷ          - lowered range = [0,1,2,...,254,255]
  Ṿ€        - unevaluate €ach = ['0','1',...,['2','5','4'],['2','5','5']]
    ṗ4      - 4th Cartesian power = ALL 256^4 lists of 4 of them
            -               (e.g.: ['0',['2','5','5'],'9',['1','0']])
        ”.  - literal '.' character
      j€    - join for €ach (e.g. ['0','.','2','5','5','.','9','.','1','0'] = "0.255.9.10")
          ċ - count occurrences of right (S) in left (that big list)

Why does the version with 65,536 IPs take 1.8 seconds? o_O
Dennis

2

Retina, 42 41 bytes

~(K`

255*
["^(("|'|]")\.?\b){4}$"L$`
$.`

Try it online! Based on a previous version of @nwellnhof's Perl 6 answer, but 1 byte saved by stealing the \.?\b trick from @Deadcode's answer. Explanation:

K`

Clear the work area.

255*

Insert 255 characters.

["^(("|'|]")\.?\b){4}$"L$`
$.`

Generate the range 0..255 separated with |s, prefixed with ^((, and suffixed with )\.?\b){4}$, thus building the regular expression ^((0|1|...255)\.?\b){4}$.

~(

Evaluate that on the original input.


1

Pip, 25 16 bytes

a~=X,256RL4J"\."

Takes the candidate IP address as a command-line argument. Try it online! or Verify all test cases

Explanation

Regex solution, essentially a port of recursive's Stax answer.

                  a is 1st cmdline arg (implicit)
    ,256          Range(256), i.e. [0 1 2 ... 255]
   X              To regex: creates a regex that matches any item from that list
                  i.e. essentially `(0|1|2|...|255)`
        RL4       Create a list with 4 copies of that regex
           J"\."  Join on this string
 ~=               Regex full-match
a                 against the input

1

JavaScript, 89 bytes

(_,r=`(${[...Array(256).keys()].join`|`})`)=>RegExp(`^${(r+'\\.').repeat(3)+r}$`).test(_)

Try it online!

Create RegExp capture groups from indexes of an array having length 256 for range 0-255 joined with | and followed by escaped . character (^(0|1...|255)\.(0|1...|255)\.(0|1...|255)\.(0|1...|255)$) repeated 3 times closing with joined array followed by $ to match end of string, return true or false result of input passed to RegExp.prototype.test().

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.