ที่อยู่ IP หรือไม่?


25

เครื่องมือสแกนเครือข่ายของคุณมักจะพิถีพิถันเกี่ยวกับอินพุตและหยุดทำงานทันทีหากคุณป้อนที่อยู่ IPv4 ที่มีอักขระที่ไม่เหมาะสมหรือมีรูปแบบไม่ถูกต้อง

ที่อยู่ IPv4 เป็นที่อยู่ตัวเลข32 บิตที่เขียนเป็นตัวเลขสี่ตัวคั่นด้วยเครื่องหมายมหัพภาค ตัวเลขแต่ละตัวสามารถเป็นศูนย์ถึง 255

เราจำเป็นต้องเขียนเครื่องมือเพื่อตรวจสอบความถูกต้องของอินพุตล่วงหน้าเพื่อหลีกเลี่ยงความผิดพลาดเหล่านั้นและเครื่องมือเฉพาะของเราคือพิถีพิถัน: รูปแบบที่ถูกต้องจะมีลักษณะa.b.c.dที่ a, b, c และ d:

  • สามารถเป็น0จำนวนธรรมชาติหรือไม่มีเลขศูนย์นำหน้าไม่มีศูนย์นำ
  • ควรอยู่ระหว่าง 0 - 255 (รวม)
  • ควรไม่ประกอบด้วยสัญลักษณ์พิเศษชอบ+, -,,และอื่น ๆ
  • ควรเป็นทศนิยม (ฐาน10)

อินพุต : สตริง

เอาต์พุต : ค่า Truthy หรือ Falsey (ยอมรับค่าตามอำเภอใจด้วย)

กรณีทดสอบ :

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
แนะนำ 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
แนะนำให้เพิ่มกรณีทดสอบ "1.2.3.4.5" (หากต้องการแยก IP ที่ยาวเกินไป) และ "999.0.0.0" (เพื่อตัด IP ที่มีขนาดใหญ่เกินไป)
Triggernometry

5
อาจจะเป็นเรื่องจู้จี้เล็กน้อย แต่คุณควรอ้างถึง "ที่อยู่ IPv4" มากกว่า "ที่อยู่ IP" - หรืออย่างน้อยพูดถึงที่ที่คุณเพิ่งหมายถึงที่อยู่ IPv4 - 1234: 5678 :: 1 ควรจะเป็นที่อยู่ IP ที่ถูกต้อง จากคำอธิบายเป็นที่ชัดเจนว่าไม่ได้มีเจตนา :)
psmears

3
@Criggie หลักฐานไม่จริงตรวจสอบทั้งหมดจริงกฎ IP4 (เช่นคนที่คุณกล่าวถึง) ก็เพื่อให้แน่ใจว่าสายป้อนไม่ผิดพลาดอื่น ๆ (น่าจะเขียนไม่ดี) app ที่เพียง แต่ช่วยให้การป้อนข้อมูลในรูปแบบที่เฉพาะเจาะจงมาก . นอกจากนี้เราจะไม่เปลี่ยนกฎของการท้าทายที่มีคำตอบมากกว่า 30 ข้อ
BradC

2
@Criggie Worth สังเกตว่า RFC ประกาศว่า "ที่อยู่เป็นความยาวคงที่ของสี่อ็อกเท็ต" ฉันคิดว่ากรณีที่คุณอ้างอิงมีความเชี่ยวชาญมากกว่าความท้าทายนี้
โผล่

คำตอบ:


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 สำหรับที่อยู่ที่ไม่ถูกต้องหรือ -1 สำหรับเมื่อตระกูลที่อยู่ไม่ใช่AF_INETหรือAF_INET6 (ซึ่งจะไม่เกิดขึ้นเพราะฉันผ่านค่าคงที่)

ดังนั้นฉันเพียงแค่ย้ายสตริงไปที่ register สำหรับอาร์กิวเมนต์ที่สองตั้งค่า register แรกเป็น 2 และตั้งค่า register ที่สามเป็นโซนสีแดง (128 bytes ใต้ตัวชี้สแต็ก) เนื่องจากฉันไม่สนใจผลลัพธ์ จากนั้นผมก็สามารถjmpที่จะinet_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 bytes-TIO 32bit x86
Logern

3
คุณควรรวม extern ในชื่อคำตอบเนื่องจากโปรแกรมต้องการและมันไม่สามารถใช้ได้ในทุกแพลตฟอร์ม
qwr

1
"mov rdi, 2" สามารถเป็น "push 2 / pop rdi" สำหรับ -2 ไบต์ โปรดทราบว่าการถอดแยกชิ้นส่วนนั้นผิดหรือรหัสผิด มันอาจเป็น "mov edi" (ไม่ใช่ rdi) หรือไม่มีคำนำหน้าหายไป
เตอร์เฟอร์รี

13

Java (JDK) , 63 ไบต์

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

ลองออนไลน์!

เครดิต

  • -1 ไบต์ต้องขอบคุณKevin Cruijssen
  • l4m2.1.1.1.1สำหรับการแสดงกรณีที่ก่อนหน้านี้ล้มเหลว

คุณลืมลบเซมิโคลอนต่อท้าย ;) และฉันสามารถตรวจสอบว่ามันใช้งานได้กับทุกกรณีทดสอบรวมถึงกรณีที่อยู่ในความคิดเห็น จะดูว่าฉันเห็นบางสิ่งที่จะเล่นกอล์ฟ
Kevin Cruijssen

3
ล้มเหลวในวันที่.1.2.3.4
l4m2

มันอนุญาตให้ใช้บูลีนเมื่อต้องมีการชี้แจง 0/1 หรือไม่?
l4m2

1
@ l4m2 คำถามเดิมมีเหตุผล / ไม่ถูกต้อง ดังนั้นฉันคิดว่าค่าความจริง / เท็จเป็นที่ยอมรับได้ที่นี่
Kevin Cruijssen

Output: 0 or 1และ Java ไม่มีระบบบูลอัตโนมัติ
l4m2

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, -1B จาก Patrick Stephansen, + 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

นี้จะช่วยให้ truthy 0.0.0.0สำหรับ ดูเหมือนว่าทุกอย่างจะทำงานได้ดี
Kevin Cruijssen

1
@KevinCruijssen 0.0.0.0อยู่ตรงนี้จริง ทำไมการฉีด SQL ถึงอยู่ที่นี่?
l4m2

เดี๋ยวก่อนฉันแปลความหมายประโยคผิดในคำอธิบายการท้าทาย 0.0.0.0เป็นความจริงแน่นอน ที่จะกอล์ฟคำตอบของฉันเป็นอย่างดี .. (? และสิ่งที่คุณหมายถึงโดยฉีด SQL: S การเชื่อมโยงคือการ TIO กับกรณีการทดสอบทั้งหมด.)
เควิน Cruijssen

1
@ l4m2 ฉันเพิ่มเพราะเราต้องการ testcase บางอย่างที่ไม่ได้ดูเหมือนที่อยู่ IP
tsh

11

PHP , 39 36 ไบต์

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

ลองออนไลน์!

275 คล้ายกับค่าคงที่ FILTER_VALIDATE_IP

5 ** 9 ถูกใช้แทนค่าคงที่ FILTER_FLAG_IPV4เป็นถูกนำมาใช้แทนการอย่างต่อเนื่อง นี่เพียงพอแล้วเพราะ5**9 & FILTER_FLAG_IPV4เป็นความจริงซึ่งเป็นสิ่งที่ PHP ทำในพื้นหลังตามที่เบอนัวต์เอสนาร์ดชี้

ที่นี่filter_varส่งคืนอาร์กิวเมนต์แรกหากเป็นที่อยู่ IPv4 ที่ถูกต้องหรือเป็นเท็จหากไม่ใช่ ด้วย+!!เราผลิตผลลัพธ์ตามความท้าทาย


3
ใช้5**9แทนการ1048576บันทึก 3 ไบต์ที่นี่: PHP ใช้&ทดสอบแฟล็ก IPv4 / IPv6ดังนั้นหมายเลขใด ๆ ระหว่าง 1048576 ถึง 2097151 จึงถูกต้อง
เบอนัวต์เอสนาร์ด

ฉันขอปฏิเสธคำตอบสำหรับการเป็น (โดยพื้นฐาน) คำตอบของฉัน: codegolf.stackexchange.com/a/174470/14732ซึ่งเขียนที่ 2018-10-22 09: 17: 34UTC ในขณะที่เขียนใน 2018-10-22 09: 21: 55UTC แม้ว่าฉันจะยกเลิกการปรับให้เหมาะสม 1 ไบต์โดย @BenoitEsnard คำตอบของฉันก็เหมือนกับของคุณในการใช้งาน
Ismael Miguel

2
ฉันต้องขออภัยฉันไม่เห็นคำตอบของคุณแม้ว่าในขณะที่ฉันเขียนมันไม่มีการส่งใน PHP ในคำถามนี้ (ตามที่คุณพูดความแตกต่างของเวลาน้อยกว่าห้านาที)
oktupol

ฉันรู้และเข้าใจ ฉันเพิ่งสังเกตเห็นคุณเพียงแค่ตอนนี้ ฉันสามารถย้อนกลับเหมืองของฉันและคุณให้การเพิ่มประสิทธิภาพ แต่ฉันไม่รู้ว่าจะทำให้คำตอบนั้นแตกต่างจากคนอื่นหรือไม่
Ismael Miguel

17
@IsmaelMiguel ฉันจะไม่ลงคะแนนใครสักคนเพื่อที่ว่าถ้าเป็นไปได้คุณไม่ได้อยู่ที่นั่นเมื่อพวกเขาเริ่ม ด้วยความแตกต่าง 5 นาทีไม่เพียง แต่เป็นไปได้เท่านั้นมันเกือบจะเป็นกรณีที่เห็นได้ชัดแม้จะไม่มีผู้เขียนที่บอกตัวเอง
Duncan X Simpson

11

PHP, 36 ไบต์

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

ip2longเป็นที่รู้จักกันดีในตัวฟังก์ชั่น



ดูเหมือนว่าจะใช้คุณสมบัติที่ไม่มีเอกสารในเวอร์ชันที่ใหม่กว่า (ฉันคิดว่ามันมาจาก PHP7 +) โปรดทราบว่าสำหรับ PHP 4 และ 5 สิ่งนี้จะยอมรับ IP ที่ไม่สมบูรณ์
Ismael Miguel



1
สิ่งนี้จะทำให้สำเร็จถ้าคุณป้อนจำนวนเต็มเช่น 1, 2 เป็นต้นอย่าคิดว่าควรทำ และถ้าคุณให้อาหารมันเป็น 100.100.100
nl-x

10

Perl 6 , 22 21 20 ไบต์

-1 ไบต์ขอบคุณ Phil H.

{?/^@(^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
ผู้ชายฉันต้องใช้เวลามากขึ้นในการหา regexes ของ Perl 6 ฉันไม่มี%ตัวแก้ไขอย่างใดอย่างหนึ่ง ฉันสงสัยว่ามันพยายามตรวจสอบ256**4ความเป็นไปได้ทั้งหมดหรือไม่?
Jo King

1
แทนที่จะ<{^256}>คุณก็สามารถแปลงช่วงที่จะอาร์เรย์@(^256)สำหรับ -1 ถ่านTIO ด้วยการเปลี่ยนโค้ดบล็อกให้เป็นอาร์เรย์มันจะเร็วขึ้นอย่างมาก (0.4s แทน> 30)
Phil H

@PhilH ขอบคุณ ฉันพยายาม$(^256)แต่ตอนนี้ฉันรู้แล้วว่าทำไมมันถึงไม่ได้
nwellnhof

9

05AB1E , 26 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

@MagicOctopusUrn ฉันเกรงว่ามันล้มเหลว1.1.1.1E1, 1..1.1.1, 1.1.1.1., และ192.00.0.255 0.00.10.255(PS: ฉันได้แก้ไขแล้ว1.1.1.1E1โดยการเพิ่มการþตรวจสอบการเข้าร่วมและเท่ากับ)
Kevin Cruijssen

ยุติธรรมพอคิดว่าฉันพลาดอะไรบางอย่าง
Magic Octopus Urn

@MagicOctopusUrn ปัญหาหลักคือ 05AB1E เห็นตัวเลขที่มีค่า 0 นำหน้าเท่ากับตัวเลขที่ไม่มีแม้จะเป็นสตริง ซึ่งเป็นเหตุผลที่ผมใช้DïþJsJQการตรวจสอบที่ïทิ้งให้ int เพื่อลบ 0s ชั้นนำและþเพียงใบตัวเลขการลบสิ่งที่ชอบE, -ฯลฯ :) สำหรับกรณีทดสอบ0.00.10.255ตั้งแต่00010255และ0010255จะเท่ากับ
Kevin Cruijssen

ใช่ฉันผ่านเรื่องไร้สาระเดียวกันกลับรายการทั้งหมดได้ค่อนข้างดียกเว้นสำหรับกรณีเหล่านั้น น่าสนใจเมื่อฟีเจอร์ที่เป็นประโยชน์สำหรับปัญหาบางอย่างเกือบจะกลายเป็นข้อบกพร่องสำหรับผู้อื่น
Magic Octopus Urn

6

PowerShell, 59 51 49 ไบต์

-8 ไบต์ขอบคุณ @AdmBorkBork

-2 ไบต์trueหรือfalseอนุญาตโดยผู้เขียน

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 ไบต์trueหรือfalseอนุญาตโดยผู้เขียน

-2 ไบต์ขอบคุณ @ Deadcodeสำหรับ regexp ที่ยอดเยี่ยม

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

ลองออนไลน์!

ขอบคุณ @ Olivier Grégoireสำหรับการแสดงออกปกติดั้งเดิม


1
คุณไม่ควรจะต้องโทร|% t*gเพราะ PowerShell จะส่งทางด้านขวาของ-eqสตริงโดยอัตโนมัติเพราะด้านซ้ายมือเป็นสตริง -try{+("$args"-eq[IPAddress]::Parse($args))}catch{0}
AdmBorkBork

คุณสามารถแกะสลัก 2 ไบต์จากรุ่น "ไม่ใช้. NET lib" โดยใช้ regex ของฉัน (ปรับให้เข้ากับเคล็ดลับการแทรกระยะเวลาซึ่งแน่นอนไม่สามารถอยู่ในรุ่นของฉันเพราะมันเป็น regex บริสุทธิ์): tio.run/…
Deadcode

5

C (gcc) / POSIX, 26 ไบต์

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

ลองออนไลน์!

ทำงานเป็นรหัส 64 บิตบน TIO แต่อาจต้องใช้sizeof(int) == sizeof(char*)กับแพลตฟอร์มอื่น


@TobySpeight ใช่ถ้าคุณใช้ x86 คุณน่าจะลองในโหมด 32 บิต ( -m32)
nwellnhof

ผมได้รับมันในการทำงานโดยผ่าน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
  • << << 20 = 1048576 = FILTER_FLAG_IPV4
  • 5 ** 9 = 1953125 (ซึ่งมีบิตที่ต้องการเป็น "1" สำหรับ 1048576)

ขอบคุณBenoit Esnardสำหรับเคล็ดลับนี้ที่ช่วยฉัน 1 ไบต์!

ขอขอบคุณติตัสที่เตือนฉันถึงความเปลี่ยนแปลงที่ท้าทาย


ฉันใช้ฟังก์ชันip2longนี้แล้ว แต่ทำงานได้กับที่อยู่ IP ที่ไม่สมบูรณ์

ที่อยู่ IPv4 ที่ไม่สมบูรณ์นั้นถือว่าไม่ถูกต้องในการท้าทายนี้

หากพวกเขาได้รับอนุญาตนี้จะเป็นรหัสสุดท้าย (เฉพาะ PHP 5.2.10):

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

ขณะนี้ยังไม่ชัดเจนในเอกสารที่ว่านี้จะหยุดทำงาน (เมื่อผ่าน ip ที่ไม่สมบูรณ์) กับ PHP รุ่นใหม่

หลังจากการทดสอบยืนยันว่าเป็นอย่างนั้น

ขอบคุณnwellnhofสำหรับคำแนะนำ!


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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.