IP地址与否?


25

您的网络扫描工具烦人地挑剔输入,如果您向它提供了包含不正确字符或格式不正确的IPv4地址,则会立即崩溃。

IPv4地址是一个32位数字地址,用四个数字隔开,每个数字用句点分隔。每个数字可以为零到255

我们需要编写一个工具来对输入进行预验证以避免这些崩溃,并且我们的特定工具很挑剔:有效的格式如下所示:a.b.c.da,b,c和d:

  • 可以是一个无前导零0的自然数。
  • 应介于0-255(含)之间。
  • 如果包含特殊符号+-,,等。
  • 应为小数(以开头10

输入:字符串

输出:真值或假​​值(也可以接受任意值)

测试用例

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)

这是,因此将赢得最少的字节!

给用户的提示 -如果您想添加更多的测试用例,欢迎您(建议进行修改)。但是,请确保测试用例不会重复!谢谢


10
建议测试用例:1.1.1.1.11.1.1.1..1.1.11..1.11..1.1.11.1.1.01.1.1.-01.1.1.+11.1.1.1E11.1.1.2561.1.1.0x1255.255.255.2550.0.0.0'or 1=1--<empty string>1 1 1 11,1,1,1
tsh

5
建议添加测试用例“ 1.2.3.4.5”(以排除太大的IP)和“ 999.0.0.0”(以排除太大的IP)。
Triggernometry '18

5
可能有些挑剔,但您可能应该指代“ IPv4地址”而不是“ IP地址”-或至少在某个地方提到您只是指IPv4地址-否则1234:5678 :: 1应该是有效的IP地址(而从描述中很明显,这不是故意的:)
psmears

3
@Criggie前提不是要真正检查所有真实的 IP4规则(如您提到的规则),而是要确保输入字符串不会使其他仅允许输入非常特定形式的应用程序崩溃(可能写得不好) 。另外,我们不会更改已经有30多个答案的挑战规则。
BradC

2
@Criggie值得指出的是,RFC声明“地址是四个八位位组的固定长度”。我认为您所引用的附带案例比此挑战更专业。

Answers:


26

X86_64机器码: 18岁 16字节

编辑:这个答案不太有效,因为

  1. 我使用inet_pton的是标准C库,这意味着我需要extern。我没有在字节数中包括extern。
  2. 我将红色区域用作实际地址的结果,但称为函数也可以使用红色区域。幸运的是,它不在我的计算机上,但是某些奇怪的标准库可能会使用它,这可能会导致未定义的行为。

是的,整个事情几乎都由一个已经编写的函数完成

无论如何,这就是我得到的: 48 89 fe 6a 02 5f 48 8d 54 24 80 e9 00 00 00 00

部件:

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

说明:

看一看inet_pton(3)。它需要一个字符串IP地址,并将其放入可以与一起使用的缓冲区中struct sockaddr。它包含3个参数:地址族(AF_INET(ipv4),2或AF_INET6(ipv6),10),ip地址的字符串以及指向输出的指针。成功返回1,无效地址返回0,或者当地址族不为AF_INET或时返回-1 AF_INET6(这将永远不会发生,因为我将常量传递给它)。

所以我只是将字符串移到第二个参数的寄存器中,将第一个寄存器设置为2,然后将第三个寄存器设置为红色区域(堆栈指针下方的128个字节),因为我不在乎结果。然后,我可以简单地jmpinet_pton其返回给呼叫者!

我启动了这个快速测试程序来测试您的案例:

#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;
}

使用进行nasm -felf64 assembly.asm编译gcc -no-pie test.c assembly.o,使用进行编译,您将获得:

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

如果调用者应该传递AF_INET或传递AF_INET6给函数,则可以将其缩小很多


4
我爱你在asm中做到这一点。而且您向可能不了解它的人(以及测试代码)解释了它的事实甚至更好。这并不是说我可以在asm中完成;已经过去了很多年,但我记得足够多,可以确切地看到您的解释(以及过程)在说什么(确实)。辛苦了
Pryftan

4
e9 00 00 00 00是一个jmp near $+5,而不是一个jmp inet_pton。如果您提供操作码,则应包括包含inet_pton部分,不要留空
l4m2

1
15字节TIO 32位x86
Logern

3
您应该在答案标题中包含extern,因为该程序需要它,并且并非在所有平台上都可用。
qwr

1
“ mov rdi,2”可以是“ push 2 / pop rdi”(-2个字节)。另请注意,反汇编错误或代码错误。它是“ mov edi”(不是rdi)或缺少前缀。
彼得·费里18-10-26

13

Java(JDK),63个字节

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

在线尝试!

学分


您忘记删除结尾的分号。;)并且我可以验证它是否适用于所有测试用例,包括注释中的那些。看看我能不能打高尔夫球。
凯文·克鲁伊森

3
失败.1.2.3.4
平方米,

明确要求0/1时是否允许使用布尔值?
l4m2 '18 -10-22

1
@ l4m2原始问题具有有效/无效。因此,我假设这里的任何真实/错误值都是可以接受的。
凯文·克鲁伊森

Output: 0 or 1而且Java没有自动bool-> int
l4m2,18年

12

JavaScript(Node.js),43字节

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

在线尝试!

JavaScript(Node.js),46字节

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

在线尝试!

二手的Arnauld零件

JavaScript(Node.js)54 53 51字节

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

在线尝试!

-2B为 0+t<256,来自Patrick Stephansen的-1B,+ 1B以避免输入1.1.1.1e-80

RegExp解决方案58 54字节

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

感谢Deadcode 3个字节


我添加了一些测试用例!
RV7


1
@KevinCruijssen 0.0.0.0在这里是真实的。这就是为什么SQL注入在这里?
l4m2

等等,我误解了挑战说明中的句子。0.0.0.0确实是真的。将高尔夫球我的回答以及..(?而什么叫SQL注入是指:S中的链接是TIO与所有测试用例。)
凯文Cruijssen

1
@ l4m2我添加了它,因为我们需要一些甚至看起来都不像IP地址的测试用例。
tsh

11

PHP39 36字节

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

在线尝试!

275像常数 FILTER_VALIDATE_IP

使用5 ** 9而不是常量FILTER_FLAG_IPV4。这足够了,因为5**9 & FILTER_FLAG_IPV4正如Benoit Esnard指出的那样是真实的,这正是PHP在后台执行的操作。

在这里,filter_var返回第一个参数(如果它是有效的IPv4地址),否则返回false。使用+!!,我们可以产生挑战所需的输出。


3
使用5**9而不是在1048576此处节省3个字节:PHP用于&测试IPv4 / IPv6标志,因此1048576和2097151之间的任何数字都是有效的。
Benoit Esnard '18

我特此投票反对您的答案(基本上)是我的答案:codegolf.stackexchange.com/a/174470/14732,它写于2018-10-22 09:17:34UTC而您的写于2018-10-22 09: 21:55 UTC。即使我还原@BenoitEsnard给出的1字节优化,我的回答也与您在功能上完全相同。
伊斯梅尔·米格尔

2
我不得不道歉,我没有看到您的答案,尽管在撰写本文时,PHP尚未对此问题进行任何提交(正如您所说,时差不到5分钟)。
oktupol

我知道,我知道。我才刚注意到你的 我可以回滚,您可以继续进行优化。但我不知道这是否使答案彼此之间足够不同。
伊斯梅尔·米格尔

17
@IsmaelMiguel如果有人认为您的加入之初并不存在,那么我不会为此投票。相差5分钟,不仅看起来合理,而且几乎可以肯定是这样,即使没有作者自己这么说也很明显。
邓肯X辛普森

11

PHP,36字节

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

ip2long是众所周知的内置函数



这似乎使用了较新版本中存在的未经编码的功能(我想它来自PHP7 +)。请记住,对于PHP 4和5,它确实接受不完整的IP。
伊斯梅尔·米格尔



1
如果您将任何整数(例如1,2等等)喂给它,将会成功。不要认为它应该这样做。另外,如果您输入的内容是100.100.100
nl-x

10

Perl 6的22个 21 20字节

-1个字节,感谢PhilH。

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

在线尝试!

说明

{                  }  # 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
伙计,我需要花更多时间弄清楚Perl 6的正则表达式。我没有一个%修饰符存在。我想知道它是否尝试检查所有256**4可能性?
Jo King

1
而是<{^256}>可以将范围转换@(^256)为-1 char TIO的数组。通过将代码块更改为数组,它也变得非常快(0.4s而不是> 30)。
Phil H

@PhilH很酷,谢谢。我尝试了一下,$(^256)但现在我意识到了为什么这没用。
nwellnhof '18 -10-25

9

05AB1E26 24 23 22 23 字节

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

-1个字节感谢@Emigna
+1字节用于1.1.1.1E1错误修正测试用例,错误地返回真实结果。

在线尝试验证所有测试用例

说明:

'.¡              '# 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
您应该可以Ā代替<d
Emigna '18

@MagicOctopusUrn恐怕是失败了1.1.1.1E11..1.1.11.1.1.1.192.00.0.255,和0.00.10.255。(PS:我已经1.1.1.1E1通过在þ
联接

公平地说,我想念什么。
魔术章鱼缸

@MagicOctopusUrn主要问题是05AB1E看到带有前导0的数字等于没有前导0的数字,甚至是字符串。这就是为什么我用的是DïþJsJQ哪里检查ï它转换成int删除前导零,并且þ只长叶子的数字删除之类的东西E-等等:)的是测试案例0.00.10.255,因为000102550010255将等于。
凯文·克鲁伊森

是的,我经历了同样的胡说八道,但是除这些情况外,所有数字的反转都非常有效。当对某些问题有益的功能对其他问题几乎像bug一样有趣。
魔术章鱼缸

6

PowerShell,59 51 49字节

-8个字节,谢谢@AdmBorkBork

-2个字节,truefalse作者允许

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

测试脚本:

$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"
}

输出:

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

说明:

该脚本尝试解析参数字符串,以构造一个.NET对象IPAddress

  • 返回$true如果object创建和参数字符串等于的字符串表示object由(归地址object.toString()
  • $false否则返回

PowerShell,59 56 54字节,“不使用.NET lib”替代

-3个字节,truefalse作者允许的

-2个字节,感谢@ Deadcode提供了出色的正则表达式。

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

在线尝试!

感谢@ OlivierGrégoire的原始正则表达式。


1
您无需调用,|% t*g因为PowerShell会自动将的右侧转换-eq为字符串,因为左侧是字符串。-– try{+("$args"-eq[IPAddress]::Parse($args))}catch{0}
AdmBorkBork

您可以使用我的正则表达式从“不要使用.NET库”版本中雕刻2个字节(适应于insert-a-period技巧,由于它是纯正则表达式,因此在我的版本中当然不能使用):tio.run/...
Deadcode

5

C(gcc) / POSIX,26个字节

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

在线尝试!

在TIO上作为64位代码工作,但sizeof(int) == sizeof(char*)在其他平台上可能需要。


@TobySpeight是的,如果您使用的是x86,则应尝试以32位模式(-m32)进行尝试。
nwellnhof '18 -10-22

我通过(s作为char*访问ILP32系统的权限)通过而得以工作,是的,我与混为一谈inet_aton()
Toby Speight,

5

PHP 7+, 37 35 32字节

这使用内置函数filter_var确认它是IPv4地址

为了使其正常工作,您需要将密钥传递i给GET请求。

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

根据falsy结果,什么都不输出(结果)或IP(truthy结果)。

您可以尝试以下方法: http://sandbox.onlinephpfunctions.com/code/639c22281ea3ba753cf7431281486d8e6e66f68e http://sandbox.onlinephpfunctions.com/code/ff6aaeb2b2d0e0ac43f48125de0549320bc071b4


这将直接使用以下值:

  • 275 = FILTER_VALIDATE_IP
  • 1 << 20 = 1048576 = FILTER_FLAG_IPV4
  • 5 ** 9 = 1953125(对于1048576,其要求的位为“ 1”)

感谢Benoit Esnard的这篇技巧为我节省了1个字节!

感谢Titus提醒我挑战的变化。


我已经研究过使用该功能ip2long,但它可用于不完整的IP地址。

在此挑战中,不完整的IPv4地址被视为无效。

如果允许,这将是最终代码(仅适用于PHP 5.2.10):

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

当前,在文档中没有明确指出这将在较新的PHP版本中停止工作(如果传递了不完整的ip)。

经过测试,确认确实如此。

感谢nwellnhof的小费!


使用5**9而不是在1<<20此处保存一个字节:PHP用于&测试IPv4 / IPv6标志,因此1048576和2097151之间的任何数字都是有效的。
Benoit Esnard '18

在较新的PHP版本中,ip2long不允许使用不完整的地址。
nwellnhof '18 -10-22

@BenoitEsnard谢谢!我已经把它添加到答案
伊斯梅尔·米格尔

@nwellnhof经过测试后,我确认是这种情况。但是,我认为使用它不是一个好主意,因为它没有明确记录。
伊斯梅尔·米格尔

+!!不需要; OP现在接受任意真实值。
泰特斯(Titus),

5

Python 3:81 78 70 69 66字节

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

循环访问所有可能的IPv4地址,获取字符串表示形式并将其与输入进行比较。嗯...需要一段时间才能运行。

编辑:通过从完整程序切换到匿名功能删除了3个字节。

EDIT2:在xnor的帮助下删除了8个字节

EDIT3:通过使用解压缩的映射而不是列表理解来删除1个字节

EDIT4:通过使用列表理解而不是ipaddress模块删除了3个字节


2
我认为您的匿名功能可以是[str(ip_address(x))for x in range(256**4)].count。也256**4可以16**8
xnor18年

5

C#(Visual C#交互式编译器)84 79 65字节

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

在线尝试!

感谢@dana,节省了-5和-14个字节!

C#(Visual C#交互式编译器),61字节

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

在线尝试!

这是一项正在进行的工作。代码使用System.Net(如果计数,则为+17字节)。如果您想知道为什么我要计数和解析:

IPAddress.TryParse方法的局限性在于它验证是否可以将字符串转换为IP地址,因此,如果提供的字符串值为“ 5”,它将视为“ 0.0.0.5”。

资源

正如@milk在评论中所说,它的确会导致前导零失败。因此,这61个字节不起作用。


1
@dana太好了。做得很好!还有四个,它将击败61个字节的解决方案!
aloisdg说,请

4

Python 2中85个82 81字节

-1字节感谢Kevin Cruijssen

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

在线尝试!

113字节答案被删除,因为它失败了1.1.1.1e-80


1
您可以打高尔夫球print 1*rprint~~r。但是+1,因为它似乎适用于目前建议的所有可能的测试用例。PS:您的113字节答案因失败1.1.1.1e-80
凯文·克鲁伊森

@KevinCruijssen谢谢!没想到这种数字符号
死貂

是不是ipaddressPython 3模块?
Farhan.K

@ Farhan.K不知道,但它工作在TIO
死貂

4

Japt,17 15字节

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

尝试运行所有测试用例,从挑战注释中验证其他测试用例


说明

我们拆分为一个数组 .,检查该的长度等于4AND并且["0","255"]从该范围中删除所有范围中的元素的长度为false(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


2
@KevinCruijssen,添加了说明。感谢那些额外的测试用例。
毛茸茸的

3

Mathematica,39 31字节

原始版本:

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

修改后的版本(感谢Misha Lavrov)

 AtomQ@*Interpreter["IPAddress"]

True如果输入的是有效IP地址,则返回该值(请尝试)。

如果你坚持要10代替,再追加7个字节是必要的:

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

由于Interpreter["IPAddress"]返回的字符串用于有效输入,而复杂的故障对象用于无效的输入,因此我们可以使用来测试有效的输入AtomQ[Interpreter["IPAddress"][#]]&,可以将其进一步简化为函数组成AtomQ@*Interpreter["IPAddress"]在线尝试!
米莎·拉夫罗夫

无法在IPv6地址上显示,例如2001:0db8:85a3:0000:0000:8a2e:0370:7334
lirtosiast


3

Python 2,93 89 67 53字节

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

在线尝试!

感谢丹尼斯剃须另一在内部比较和退出代码上 14个字节。

特别感谢Jonathan Allan节省了22个字节并修复了逻辑问题!讨厌的尝试/除非死神!

感谢乔·金(Jo King),采用格式正确的字符串而不是原始字节可以减少4个字节。


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().

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.