นิพจน์ทั่วไปที่ตรงกับที่อยู่ IPv6 ที่ถูกต้อง


111

ฉันมีปัญหาในการเขียนนิพจน์ทั่วไปที่ตรงกับที่อยู่ IPv6 ที่ถูกต้องรวมถึงที่อยู่ในรูปแบบบีบอัด (ที่มี::เลขศูนย์นำหน้าละเว้นจากคู่ไบต์แต่ละคู่)

ใครสามารถแนะนำนิพจน์ทั่วไปที่จะตอบสนองความต้องการได้หรือไม่?

ฉันกำลังพิจารณาขยายคู่ไบต์แต่ละคู่และจับคู่ผลลัพธ์ด้วย regex ที่ง่ายกว่า


1
ตรวจสอบintermapper.com/ipv6validator .. ลิงก์ไปยังสคริปต์ทดสอบ perl
Mottie

ฉันได้ลองคำตอบด้านล่างทั้งหมดแล้วและไม่ได้ผลกับกรณีทดสอบทั้งหมดของฉันและ / หรือรวมถึง IPv4 ที่ไม่ได้ถามด้วย ฉันพบว่านี่เป็นวิธีแก้ปัญหาที่สะอาดที่สุด: stackoverflow.com/a/21944928/3112803
gfrobenius

คำตอบ:


252

ฉันไม่สามารถรับคำตอบของ @Factor Mystic ในการทำงานกับนิพจน์ทั่วไปของ POSIX ได้ดังนั้นฉันจึงเขียนนิพจน์ทั่วไปที่ใช้ได้กับนิพจน์ทั่วไป POSIX และนิพจน์ทั่วไป PERL

ควรตรงกับ:

นิพจน์ทั่วไปของ IPv6:

(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))

เพื่อความสะดวกในการอ่านต่อไปนี้คือนิพจน์ทั่วไปด้านบนที่แยกประเด็นสำคัญหรือออกเป็นบรรทัดแยกกัน

# IPv6 RegEx
(
([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|          # 1:2:3:4:5:6:7:8
([0-9a-fA-F]{1,4}:){1,7}:|                         # 1::                              1:2:3:4:5:6:7::
([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|         # 1::8             1:2:3:4:5:6::8  1:2:3:4:5:6::8
([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|  # 1::7:8           1:2:3:4:5::7:8  1:2:3:4:5::8
([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|  # 1::6:7:8         1:2:3:4::6:7:8  1:2:3:4::8
([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|  # 1::5:6:7:8       1:2:3::5:6:7:8  1:2:3::8
([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|  # 1::4:5:6:7:8     1:2::4:5:6:7:8  1:2::8
[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|       # 1::3:4:5:6:7:8   1::3:4:5:6:7:8  1::8  
:((:[0-9a-fA-F]{1,4}){1,7}|:)|                     # ::2:3:4:5:6:7:8  ::2:3:4:5:6:7:8 ::8       ::     
fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|     # fe80::7:8%eth0   fe80::7:8%1     (link-local IPv6 addresses with zone index)
::(ffff(:0{1,4}){0,1}:){0,1}
((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}
(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|          # ::255.255.255.255   ::ffff:255.255.255.255  ::ffff:0:255.255.255.255  (IPv4-mapped IPv6 addresses and IPv4-translated addresses)
([0-9a-fA-F]{1,4}:){1,4}:
((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}
(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])           # 2001:db8:3:4::192.0.2.33  64:ff9b::192.0.2.33 (IPv4-Embedded IPv6 Address)
)

# IPv4 RegEx
((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])

เพื่อให้เข้าใจง่ายขึ้นข้างต้นโค้ด "หลอก" ต่อไปนี้จะจำลองโค้ดด้านบน:

IPV4SEG  = (25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])
IPV4ADDR = (IPV4SEG\.){3,3}IPV4SEG
IPV6SEG  = [0-9a-fA-F]{1,4}
IPV6ADDR = (
           (IPV6SEG:){7,7}IPV6SEG|                # 1:2:3:4:5:6:7:8
           (IPV6SEG:){1,7}:|                      # 1::                                 1:2:3:4:5:6:7::
           (IPV6SEG:){1,6}:IPV6SEG|               # 1::8               1:2:3:4:5:6::8   1:2:3:4:5:6::8
           (IPV6SEG:){1,5}(:IPV6SEG){1,2}|        # 1::7:8             1:2:3:4:5::7:8   1:2:3:4:5::8
           (IPV6SEG:){1,4}(:IPV6SEG){1,3}|        # 1::6:7:8           1:2:3:4::6:7:8   1:2:3:4::8
           (IPV6SEG:){1,3}(:IPV6SEG){1,4}|        # 1::5:6:7:8         1:2:3::5:6:7:8   1:2:3::8
           (IPV6SEG:){1,2}(:IPV6SEG){1,5}|        # 1::4:5:6:7:8       1:2::4:5:6:7:8   1:2::8
           IPV6SEG:((:IPV6SEG){1,6})|             # 1::3:4:5:6:7:8     1::3:4:5:6:7:8   1::8
           :((:IPV6SEG){1,7}|:)|                  # ::2:3:4:5:6:7:8    ::2:3:4:5:6:7:8  ::8       ::       
           fe80:(:IPV6SEG){0,4}%[0-9a-zA-Z]{1,}|  # fe80::7:8%eth0     fe80::7:8%1  (link-local IPv6 addresses with zone index)
           ::(ffff(:0{1,4}){0,1}:){0,1}IPV4ADDR|  # ::255.255.255.255  ::ffff:255.255.255.255  ::ffff:0:255.255.255.255 (IPv4-mapped IPv6 addresses and IPv4-translated addresses)
           (IPV6SEG:){1,4}:IPV4ADDR               # 2001:db8:3:4::192.0.2.33  64:ff9b::192.0.2.33 (IPv4-Embedded IPv6 Address)
           )

ฉันโพสต์สคริปต์บน GitHub ซึ่งทดสอบนิพจน์ทั่วไป: https://gist.github.com/syzdek/6086792


3
คุณ IPv4 regex ไม่ตรงกับ IPs เช่น127.000.000.001
Kentzo

21
ส่วน IPv4 ไม่ควรมีเลขศูนย์นำหน้า หากมีศูนย์นำหน้าเซ็กเมนต์ IPv4 ควรตีความเป็นฐานแปด ดังนั้น IPV4SEG ข้างต้นจึงถูกต้องในการไม่อนุญาต '000' อย่างไรก็ตามไม่อนุญาตให้ใช้ '00' ซึ่งไม่ควร
พาร์

3
ไม่ได้ผลสำหรับฉันในเบราว์เซอร์อย่างที่ฉันคาดหวัง ตรวจสอบได้แม้กระทั่ง reg.test ('3zzzzffe: 1900: 4545: 3: 200: f8ff: fe21: 67cf') ซึ่งเห็นได้ชัดว่าไม่ใช่ที่อยู่ IPv6 ที่ถูกต้อง มีผลลัพธ์ที่ดีกว่ามากกับ regex ที่นี่: nbviewer.ipython.org/github/rasbt/python_reference/blob/master/…
Capaj

7
regex ipv6 ที่ยอดเยี่ยม พบข้อบกพร่องเล็ก ๆ กับส่วนเชื่อมโยงภายใน คุณมีfe80ที่มันควรจะเป็นสิ่งที่ชอบ[fF][eE]80และffffที่ควรจะเป็นสิ่งที่ชอบ[fF]{4}
user2831628

4
+1 เพื่อแสดงว่า regexes สามารถ (ในลักษณะเดียวกับซอร์สโค้ด) สามารถอ่านได้จริงหากคุณดูแลและจัดรูปแบบ
Natix

52

ต่อไปนี้จะตรวจสอบความถูกต้องของที่อยู่ IPv4, IPv6 (เต็มและบีบอัด) และ IPv6v4 (เต็มและบีบอัด):

'/^(?>(?>([a-f0-9]{1,4})(?>:(?1)){7}|(?!(?:.*[a-f0-9](?>:|$)){8,})((?1)(?>:(?1)){0,6})?::(?2)?)|(?>(?>(?1)(?>:(?1)){5}:|(?!(?:.*[a-f0-9]:){6,})(?3)?::(?>((?1)(?>:(?1)){0,4}):)?)?(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(?>\.(?4)){3}))$/iD'

8
แม้ว่าการตรวจสอบความถูกต้อง ip-s สามารถทำได้ตามที่ Frank Krueger แนะนำ แต่โซลูชันนี้เป็นวิธีที่ตอบคำถามได้จริง (แม้ว่าฉันจะยังไม่ได้ทดสอบอย่างสมบูรณ์) รวมถึงหากคุณมี IP-s จำนวนมากที่คุณต้องการทดสอบทางวากยสัมพันธ์ และอาจจับคู่ในบรรทัดข้อความคุณไม่สามารถใช้เทคนิคการตรวจสอบ IP ได้
Gyuri

สวัสดีฉันทดสอบ RegExp นี้แล้วและไม่ได้ผลสำหรับฉัน มันบอกว่า D เป็นค่าสถานะที่ไม่ถูกต้องและเมื่อฉันลบออกมันจะขึ้นว่า "SyntaxError: invalid quantifier"
diosney

3
JavaScript ใช้ชุดย่อยของนิพจน์ทั่วไปสไตล์ Perl ไม่ใช่ PCRE ทั้งหมด regex ของฉันจะไม่ทำงานหากไม่มีคุณสมบัติขั้นสูงของ PCRE
MichaelRushton

2
สิ่งนี้ให้ข้อยกเว้นสำหรับฉันใน C #
sarat

1
กรณีทดสอบที่ล้มเหลว: FE80: 0000: 0000: 0000: 0202: B3FF: FE1E: 8329 ใช้ Elixir เวอร์ชันล่าสุดในวันที่นี้ซึ่งใช้ PCRE อยู่ข้างใต้
pmarreck

23

ดูเหมือนว่าคุณอาจใช้ Python ในกรณีนี้คุณสามารถใช้สิ่งนี้:

import socket

def check_ipv6(n):
    try:
        socket.inet_pton(socket.AF_INET6, n)
        return True
    except socket.error:
        return False

print check_ipv6('::1') # True
print check_ipv6('foo') # False
print check_ipv6(5)     # TypeError exception
print check_ipv6(None)  # TypeError exception

ฉันไม่คิดว่าคุณต้องคอมไพล์ IPv6 ใน Python เพื่อรับinet_ptonซึ่งสามารถแยกวิเคราะห์ที่อยู่ IPv4 ได้หากคุณส่งผ่านsocket.AF_INETเป็นพารามิเตอร์แรก หมายเหตุ: สิ่งนี้อาจใช้ไม่ได้กับระบบที่ไม่ใช่ Unix


4
คุณควรระบุประเภทข้อยกเว้นในexceptข้อ มิฉะนั้นexceptจะจับทุกอย่างและอาจปกปิดข้อผิดพลาดที่ไม่เกี่ยวข้อง socket.errorประเภทของที่นี่ควรจะเป็น
Ayman Hourieh

A) inet_pton ไม่ทิ้งข้อยกเว้นอื่น ๆ เว้นแต่ว่าเอกสารจะผิดและ B) แม้ว่าจะทำเช่นนั้นคุณจะส่งคืนอะไรอีก แต่เป็นเท็จ
Joe Hildebrand

2
Re: ข้อผิดพลาดอื่น ๆ ... หากผู้ใช้ส่งผ่านแบบไม่ใช่สตริง TypeError จะถูกกิน เห็นได้ชัดว่ารายการไม่ใช่ ipv6 แต่ฉันอาจต้องการมีปลาคาร์พที่ฉันส่งผิดประเภท
Gregg Lind

1
+1 สิ่งนี้ช่วยฉันได้มาก จุดเพิ่มเติมสองสามข้อที่ควรเพิ่ม: 1) สามารถใช้ socket.inet_pton เพื่อทดสอบความถูกต้องของที่อยู่ IP ทั้งสองตระกูล (IP และ IPv6) 2) เอกสารที่นี่ ( docs.python.org/2/library/socket.html ) แนะนำว่าพร้อมใช้งานบนแพลตฟอร์ม Unix อาจไม่มีให้บริการบนแพลตฟอร์ม Win
mkoistinen

ใช้ django และสิ่งนี้ช่วยได้!
รับเงิน

23

จาก " IPv6 regex ":

(\A([0-9a-f]{1,4}:){1,1}(:[0-9a-f]{1,4}){1,6}\Z)|
(\A([0-9a-f]{1,4}:){1,2}(:[0-9a-f]{1,4}){1,5}\Z)|
(\A([0-9a-f]{1,4}:){1,3}(:[0-9a-f]{1,4}){1,4}\Z)|
(\A([0-9a-f]{1,4}:){1,4}(:[0-9a-f]{1,4}){1,3}\Z)|
(\A([0-9a-f]{1,4}:){1,5}(:[0-9a-f]{1,4}){1,2}\Z)|
(\A([0-9a-f]{1,4}:){1,6}(:[0-9a-f]{1,4}){1,1}\Z)|
(\A(([0-9a-f]{1,4}:){1,7}|:):\Z)|
(\A:(:[0-9a-f]{1,4}){1,7}\Z)|
(\A((([0-9a-f]{1,4}:){6})(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3})\Z)|
(\A(([0-9a-f]{1,4}:){5}[0-9a-f]{1,4}:(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3})\Z)|
(\A([0-9a-f]{1,4}:){5}:[0-9a-f]{1,4}:(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}\Z)|
(\A([0-9a-f]{1,4}:){1,1}(:[0-9a-f]{1,4}){1,4}:(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}\Z)|
(\A([0-9a-f]{1,4}:){1,2}(:[0-9a-f]{1,4}){1,3}:(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}\Z)|
(\A([0-9a-f]{1,4}:){1,3}(:[0-9a-f]{1,4}){1,2}:(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}\Z)|
(\A([0-9a-f]{1,4}:){1,4}(:[0-9a-f]{1,4}){1,1}:(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}\Z)|
(\A(([0-9a-f]{1,4}:){1,5}|:):(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}\Z)|
(\A:(:[0-9a-f]{1,4}){1,5}:(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}\Z)

45
การแสดงออกปกติเช่นนี้ควรเป็น "กลิ่นรหัส" ซึ่งบางทีนิพจน์ทั่วไปอาจไม่ใช่วิธีแก้ปัญหาที่เหมาะสมที่สุด (แม้ว่าฉันเดาว่าฝ่ายปฏิบัติการขอมัน ... )
Thanatos

10
@ user712092 - ทุกคนที่เห็นโค้ดเบสด้วยสายตาแบบนั้น
danielpops

2
นี่คือการเลียนแบบ REs ที่ไม่จำเป็นอย่างยิ่ง โปรแกรมที่สร้างมันไม่เข้าใจว่ามันทำอะไร มนุษย์ไม่เคยทำเช่นนี้ อย่าหลงกลกับความซับซ้อนที่เห็นได้ชัด - REs เป็น "มนต์ดำ" สำหรับคนจำนวนมาก แต่ไม่มีเหตุผลที่จะวางไว้บนดาวดวงอื่น!
Chuck Kollars

+1 แต่ OMG ต้องมีวิธีที่ดีกว่านี้: P สำหรับการอ้างอิง: สำหรับ Rails สิ่งนี้อาจช่วยได้: stackoverflow.com/questions/16965697/…
Tilo

1
มันเป็นกลิ่นรหัส อย่างไรก็ตามหลังจากดูแล้วคุณจะเห็นว่า regex แต่ละรายการค่อนข้างรัดกุม ปัญหาคือมีรูปแบบที่แตกต่างกันที่สร้างขึ้นโดย 'การบีบอัด' ของ ipv6 - โคลอนเริ่มต้นกลางและท้ายหากคุณใช้โคลอนคู่แล้วคุณจะไม่สามารถใช้มันได้อีก เครื่องหมายทวิภาคก่อนและหลังคู่จะต้องรวมกัน Perl 6 อาจจะสามารถที่จะแก้ไขปัญหานี้ แต่มันเป็นวิธีที่เกินไวยากรณ์ PCRE (ป.ล. - ฉันไม่นับ ipv4 ที่ฝังไว้ตอนท้ายซึ่งยาวกว่าส่วน ipv6!)
เจอราร์ด

11

ฉันต้องขอคำตอบจากFrank Krueger เป็นอย่างยิ่ง

ในขณะที่คุณบอกว่าคุณต้องการนิพจน์ทั่วไปเพื่อให้ตรงกับที่อยู่ IPv6 ฉันคิดว่าสิ่งที่คุณต้องการจริงๆคือสามารถตรวจสอบได้ว่าสตริงที่กำหนดเป็นที่อยู่ IPv6 ที่ถูกต้องหรือไม่ มีความแตกต่างที่ลึกซึ้ง แต่สำคัญที่นี่

มีมากกว่าหนึ่งวิธีในการตรวจสอบว่าสตริงที่ระบุเป็นที่อยู่ IPv6 ที่ถูกต้องหรือไม่และการจับคู่นิพจน์ทั่วไปเป็นเพียงวิธีเดียว

ใช้ไลบรารีที่มีอยู่ถ้าคุณทำได้ ไลบรารีจะมีบั๊กน้อยลงและการใช้งานจะส่งผลให้คุณรักษาโค้ดน้อยลง

นิพจน์ทั่วไปที่แนะนำโดยFactor Mysticนั้นยาวและซับซ้อน เป็นไปได้มากที่สุด แต่คุณควรพิจารณาด้วยว่าคุณจะรับมืออย่างไรหากล้มเหลวโดยไม่คาดคิด ประเด็นที่ฉันพยายามจะทำให้ตรงนี้คือถ้าคุณไม่สามารถสร้างนิพจน์ทั่วไปที่ต้องการได้ด้วยตัวเองคุณจะไม่สามารถดีบักได้อย่างง่ายดาย

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

ปฏิบัติด้วยความระมัดระวังเมื่อใช้นิพจน์ทั่วไปซึ่งคุณไม่สามารถอธิบายฟังก์ชันการทำงานให้คนอื่นเข้าใจได้


1
การใช้นิพจน์ทั่วไปสองนิพจน์นิพจน์เสรีและนิพจน์ข้อยกเว้นเพื่อดักจับแอดเดรสที่ไม่ถูกต้องที่อนุญาตโดยนิพจน์แรกอาจง่ายกว่าหนึ่งนิพจน์ ( return ex1.match(S) && ! ex2.match(S))
Raedwald

4
คุณกำลังสมมติว่าเขากำลังตรวจสอบความถูกต้องของแต่ละ IP เมื่อเขาค้นหา IP ในข้อความจำนวนมาก
Navin

8

ฉันไม่ใช่ผู้เชี่ยวชาญ Ipv6 แต่ฉันคิดว่าคุณจะได้รับผลลัพธ์ที่ดีงามได้ง่ายขึ้นด้วยอันนี้:

^([0-9A-Fa-f]{0,4}:){2,7}([0-9A-Fa-f]{1,4}$|((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.|$)){4})$

เพื่อตอบว่า "เป็น ipv6 ที่ถูกต้อง" ดูเหมือนว่าโอเคสำหรับฉัน เพื่อทำลายมันเป็นส่วน ๆ ... ลืมไป ฉันได้ละเว้นสิ่งที่ไม่ระบุ (: :) เนื่องจากไม่มีประโยชน์ที่จะมี "ที่อยู่ที่ไม่ได้ระบุ" ในฐานข้อมูลของฉัน

จุดเริ่มต้น: ^([0-9A-Fa-f]{0,4}:){2,7}<- ตรงกับส่วนที่บีบอัดได้เราสามารถแปลสิ่งนี้เป็น: ระหว่าง 2 ถึง 7 โคลอนซึ่งอาจมีจำนวนทศนิยมระหว่างพวกเขา

ตามด้วย: [0-9A-Fa-f]{1,4}$<- เลขฐานสิบหก (เว้นเลขนำหน้า 0) หรือ ((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.|$)){4}<- ที่อยู่ Ipv4


1
+1 สำหรับการตอบคำถาม OPs และนำเสนอ regex ที่ค่อนข้างหล่อซึ่งใช้งานได้ดี
xebeche

1
รายการนี้ไม่ตรงกับ ":: 1"
lsalamon

ฮะ? ใน java regex syntaxt ตรงกับ:start() = 0, end() = 3 group(0) = "::1" group(1) = ":" group(2) = "1" group(3) = "null" group(4) = "null" group(5) = "null"
Remi Morin

ที่อื่นมีคนแจ้งปัญหากับ regex ของฉันส่วนที่บีบอัด "::" จะปรากฏได้เพียงครั้งเดียว ดังนั้น ":: 1 :: 2" จะตรงกับ regex ของฉัน แต่ไม่ใช่ IPV6 ที่ถูกต้อง นิพจน์ที่สองอาจตรวจสอบกรณีนี้ได้ คำแนะนำทั้งหมดคือการใช้ตัวแยกวิเคราะห์สถานะเพื่อตรวจสอบความถูกต้อง ฉันยอมรับว่าโค้ดผลลัพธ์จะอ่านและดูแลรักษาได้ง่ายขึ้น (และอาจมีคนเขียนโค้ดไว้แล้วในโอเพนซอร์สที่ไหนสักแห่ง)
Remi Morin

8

สิ่งนี้จับลูปแบ็ค (:: 1) เช่นกันและที่อยู่ ipv6 เปลี่ยน {} เป็น + และใส่: ภายในวงเล็บเหลี่ยมแรก

([a-f0-9:]+:+)+[a-f0-9]+

ทดสอบกับ ifconfig -a เอาต์พุต http://regexr.com/

ตัวเลือก Unix หรือ Mac OSx เทอร์มินัล o ส่งคืนเฉพาะเอาต์พุตที่ตรงกัน (ipv6) รวมถึง ::

ifconfig -a | egrep -o '([a-f0-9:]+:+)+[a-f0-9]+'

รับที่อยู่ IP ทั้งหมด (IPv4 หรือ IPv6) และพิมพ์การจับคู่กับคำศัพท์ unix OSx

ifconfig -a | egrep -o '([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}) | (([a-f0-9:]+:+)+[a-f0-9]+)'

ฉันชอบความเรียบง่าย ในที่สุดสิ่งนี้ก็ได้ผลสำหรับฉัน:ip a | grep -Po '[\w:]+:+[\w:]+'
Noam Manos

ขำขัน!
Soumya Kanti

เมื่อฉันเรียกใช้ ipconfig / all ที่อยู่ IP ของฉันจะลงท้ายด้วย% 10 นิพจน์นี้ไม่ตรงกับส่วนนี้?
ปีเตอร์

7

นิพจน์ทั่วไปนี้จะจับคู่ที่อยู่ IPv6 และ IPv4 ที่ถูกต้องตามการใช้งาน GNU C ++ ของ regex ด้วยโหมด REGULAR EXTENDED ที่ใช้:

"^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}))|:)))(%.+)?\s*$"

5

ระวัง! ใน Java การใช้ InetAddress และคลาสที่เกี่ยวข้อง (Inet4Address, Inet6Address, URL) อาจเกี่ยวข้องกับเครือข่าย trafic! เช่นการแก้ไข DNS (URL.equals, InetAddress จากสตริง!) การโทรนี้อาจใช้เวลานานและกำลังบล็อกอยู่!

สำหรับ IPv6 ฉันมีบางอย่างเช่นนี้ แน่นอนว่านี่ไม่ได้จัดการกับรายละเอียดที่ละเอียดอ่อนของ IPv6 เช่นเดียวกับดัชนีโซนนั้นได้รับอนุญาตในที่อยู่ IPv6 บางคลาสเท่านั้น และ regex นี้ไม่ได้เขียนขึ้นเพื่อการจับภาพเป็นกลุ่ม แต่เป็น regexp ประเภท "ตรงกัน" เท่านั้น

S - ส่วน IPv6 = [0-9a-f]{1,4}

I - IPv4 = (?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9]{1,2})\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9]{1,2})

แผนผัง (ส่วนแรกตรงกับที่อยู่ IPv6 กับส่วนต่อท้าย IPv4 ส่วนที่สองตรงกับที่อยู่ IPv6 สุดท้าย patrt ดัชนีโซน):

(
(
::(S:){0,5}|
S::(S:){0,4}|
(S:){2}:(S:){0,3}|
(S:){3}:(S:){0,2}|
(S:){4}:(S:)?|
(S:){5}:|
(S:){6}
)
I

|

:(:|(:S){1,7})|
S:(:|(:S){1,6})|
(S:){2}(:|(:S){1,5})|
(S:){3}(:|(:S){1,4})|
(S:){4}(:|(:S){1,3})|
(S:){5}(:|(:S){1,2})|
(S:){6}(:|(:S))|
(S:){7}:|
(S:){7}S
)

(?:%[0-9a-z]+)?

และนี่คือ regex ที่อาจเกิดขึ้น (ไม่คำนึงถึงตัวพิมพ์เล็กและใหญ่ล้อมรอบด้วยสิ่งที่จำเป็นเช่นจุดเริ่มต้น / จุดสิ้นสุดของบรรทัด ฯลฯ ):

(?:
(?:
::(?:[0-9a-f]{1,4}:){0,5}|
[0-9a-f]{1,4}::(?:[0-9a-f]{1,4}:){0,4}|
(?:[0-9a-f]{1,4}:){2}:(?:[0-9a-f]{1,4}:){0,3}|
(?:[0-9a-f]{1,4}:){3}:(?:[0-9a-f]{1,4}:){0,2}|
(?:[0-9a-f]{1,4}:){4}:(?:[0-9a-f]{1,4}:)?|
(?:[0-9a-f]{1,4}:){5}:|
(?:[0-9a-f]{1,4}:){6}
)
(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9]{1,2})\.){3}
(?:25[0-5]|2[0-4][0-9]|[01]?[0-9]{1,2})|

:(?::|(?::[0-9a-f]{1,4}){1,7})|
[0-9a-f]{1,4}:(?::|(?::[0-9a-f]{1,4}){1,6})|
(?:[0-9a-f]{1,4}:){2}(?::|(?::[0-9a-f]{1,4}){1,5})|
(?:[0-9a-f]{1,4}:){3}(?::|(?::[0-9a-f]{1,4}){1,4})|
(?:[0-9a-f]{1,4}:){4}(?::|(?::[0-9a-f]{1,4}){1,3})|
(?:[0-9a-f]{1,4}:){5}(?::|(?::[0-9a-f]{1,4}){1,2})|
(?:[0-9a-f]{1,4}:){6}(?::|(?::[0-9a-f]{1,4}))|
(?:[0-9a-f]{1,4}:){7}:|
(?:[0-9a-f]{1,4}:){7}[0-9a-f]{1,4}
)

(?:%[0-9a-z]+)?

4

regex ต่อไปนี้ใช้สำหรับ IPv6 เท่านั้น กลุ่ม 1 ตรงกับ IP

(([0-9a-fA-F]{0,4}:){1,7}[0-9a-fA-F]{0,4})

+1 ไม่จำเป็นเสมอไปที่จะต้องมี regex super complex ที่สมบูรณ์แบบที่มนุษย์ไม่สามารถเข้าใจได้ ฉันจะใช้อันนี้เพราะฉันเข้าใจว่ามันทำอะไรและในกรณีของฉันฉันมั่นใจได้ว่าถ้าฉันมีบางอย่างที่คล้ายกับ ipv6 ที่ถูกต้องดังนั้นมันจึงเป็น ipv6 ที่ถูกต้อง
David L.

3
สิ่งนี้จะไม่ตรงกับ say: fe80 :: 1 หรือ 2342: 32fd :: 2d32
James

3

นิพจน์ทั่วไปที่จะจับคู่ แต่ฉันไม่แนะนำให้ตรวจสอบความถูกต้องของประเภทใด ๆ คือ:

([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}

โปรดทราบว่าสิ่งนี้จะจับคู่การบีบอัดที่ใดก็ได้ในที่อยู่แม้ว่าจะไม่ตรงกับที่อยู่ย้อนกลับ :: 1. ฉันพบว่านี่เป็นการประนีประนอมที่สมเหตุสมผลเพื่อให้ regex เรียบง่าย

ฉันใช้สิ่งนี้สำเร็จในกฎการเลือกอัจฉริยะของ iTerm2 เพื่อคลิกที่อยู่ IPv6 แบบสี่คลิก


3
คุณหมายถึงA-Fไม่ใช่A-Z! โปรดทราบว่าคุณไม่รวมสัญกรณ์ dotted-quad
xebeche

3

หากคุณใช้ Perl ให้ลองใช้Net :: IPv6Addr

use Net::IPv6Addr;

if( defined Net::IPv6Addr::is_ipv6($ip_address) ){
  print "Looks like an ipv6 address\n";
}

NetAddr :: IP

use NetAddr::IP;

my $obj = NetAddr::IP->new6($ip_address);

ตรวจสอบ :: IP

use Validate::IP qw'is_ipv6';

if( is_ipv6($ip_address) ){
  print "Looks like an ipv6 address\n";
}


2

ในScalaใช้ตัวตรวจสอบความถูกต้องของ Apache Commons ที่รู้จักกันดี

http://mvnrepository.com/artifact/commons-validator/commons-validator/1.4.1

libraryDependencies += "commons-validator" % "commons-validator" % "1.4.1"


import org.apache.commons.validator.routines._

/**
 * Validates if the passed ip is a valid IPv4 or IPv6 address.
 *
 * @param ip The IP address to validate.
 * @return True if the passed IP address is valid, false otherwise.
 */  
 def ip(ip: String) = InetAddressValidator.getInstance().isValid(ip)

ทำตามการทดสอบของวิธีการip(ip: String):

"The `ip` validator" should {
  "return false if the IPv4 is invalid" in {
    ip("123") must beFalse
    ip("255.255.255.256") must beFalse
    ip("127.1") must beFalse
    ip("30.168.1.255.1") must beFalse
    ip("-1.2.3.4") must beFalse
  }

  "return true if the IPv4 is valid" in {
    ip("255.255.255.255") must beTrue
    ip("127.0.0.1") must beTrue
    ip("0.0.0.0") must beTrue
  }

  //IPv6
  //@see: http://www.ronnutter.com/ipv6-cheatsheet-on-identifying-valid-ipv6-addresses/
  "return false if the IPv6 is invalid" in {
    ip("1200::AB00:1234::2552:7777:1313") must beFalse
  }

  "return true if the IPv6 is valid" in {
    ip("1200:0000:AB00:1234:0000:2552:7777:1313") must beTrue
    ip("21DA:D3:0:2F3B:2AA:FF:FE28:9C5A") must beTrue
  }
}

ที่น่าสนใจคืออ้างว่าตรวจสอบว่าเป็นที่อยู่ที่ถูกต้อง " ตรวจสอบว่า ip ที่ส่งผ่านเป็นที่อยู่ IPv4 หรือ IPv6 ที่ถูกต้อง " แต่จริงๆแล้วจะตรวจสอบว่าได้รับการจัดรูปแบบเป็นที่อยู่ที่ถูกต้องเท่านั้น ตัวอย่างเช่น1200:0000:AB00:1234:0000:2552:7777:1313เป็นรูปแบบที่ถูกต้องสำหรับที่อยู่ IPv6 แต่ไม่ใช่ที่อยู่ IPv6 ที่ถูกต้องเนื่องจากวิธีการทดสอบส่งกลับ ฉันจะพนันว่ามันคิดว่า241.54.113.65เป็นที่อยู่ IPv4 ที่ถูกต้อง
Ron Maupin

2

ดูรูปแบบที่รวมอยู่ในคำตอบอื่น ๆ มีรูปแบบที่ดีจำนวนมากที่สามารถปรับปรุงได้โดยการอ้างอิงกลุ่มและใช้ Lookaheads นี่คือตัวอย่างของรูปแบบที่อ้างอิงตัวเองซึ่งฉันจะใช้ใน PHP ถ้าฉันต้อง:

^(?<hgroup>(?<hex>[[:xdigit:]]{0,4}) # grab a sequence of up to 4 hex digits
                                     # and name this pattern for usage later
     (?<!:::):{1,2})                 # match 1 or 2 ':' characters
                                     # as long as we can't match 3
 (?&hgroup){1,6} # match our hex group 1 to 6 more times
 (?:(?:
    # match an ipv4 address or
    (?<dgroup>2[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3}(?&dgroup)
    # match our hex group one last time
    |(?&hex))$

หมายเหตุ: PHP มีตัวกรองในตัวซึ่งน่าจะเป็นทางออกที่ดีกว่ารูปแบบนี้

การวิเคราะห์ Regex101


2

ฉันสร้างสิ่งต่อไปนี้โดยใช้ python และทำงานกับโมดูล re การยืนยันล่วงหน้าเพื่อให้แน่ใจว่าจำนวนจุดหรือเครื่องหมายทวิภาคที่ถูกต้องปรากฏในที่อยู่ ไม่รองรับ IPv4 ในรูปแบบ IPv6

pattern = '^(?=\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$)(?:(?:25[0-5]|[12][0-4][0-9]|1[5-9][0-9]|[1-9]?[0-9])\.?){4}$|(?=^(?:[0-9a-f]{0,4}:){2,7}[0-9a-f]{0,4}$)(?![^:]*::.+::[^:]*$)(?:(?=.*::.*)|(?=\w+:\w+:\w+:\w+:\w+:\w+:\w+:\w+))(?:(?:^|:)(?:[0-9a-f]{4}|[1-9a-f][0-9a-f]{0,3})){0,8}(?:::(?:[0-9a-f]{1,4}(?:$|:)){0,6})?$'
result = re.match(pattern, ip)
if result: result.group(0)

2

Regexes สำหรับ ipv6 อาจยุ่งยากมากเมื่อคุณพิจารณาที่อยู่ที่มี ipv4 ฝังอยู่และที่อยู่ที่ถูกบีบอัดดังที่คุณเห็นจากคำตอบเหล่านี้

ไลบรารี IPAddress Java แบบโอเพนซอร์สจะตรวจสอบการแสดงมาตรฐานทั้งหมดของ IPv6 และ IPv4 และยังรองรับความยาวของคำนำหน้า (และการตรวจสอบความถูกต้อง) Disclaimer: ฉันเป็นผู้จัดการโครงการของห้องสมุดนั้น

ตัวอย่างโค้ด:

        try {
            IPAddressString str = new IPAddressString("::1");
            IPAddress addr = str.toAddress();
            if(addr.isIPv6() || addr.isIPv6Convertible()) {
                IPv6Address ipv6Addr = addr.toIPv6();
            }
            //use address
        } catch(AddressStringException e) {
            //e.getMessage has validation error
        }


1

เป็นการยากที่จะค้นหานิพจน์ทั่วไปที่ใช้ได้กับเคส IPv6 ทั้งหมด มักจะดูแลรักษายากไม่สามารถอ่านได้ง่ายและอาจทำให้เกิดปัญหาด้านประสิทธิภาพ ดังนั้นฉันต้องการแบ่งปันโซลูชันทางเลือกที่ฉันได้พัฒนา: Regular Expression (RegEx) สำหรับ IPv6 แยกจาก IPv4

ตอนนี้คุณอาจถามว่า "วิธีนี้พบเฉพาะ IPv6 ฉันจะค้นหา IPv6 ในข้อความหรือไฟล์ได้อย่างไร" นี่คือวิธีการสำหรับปัญหานี้ด้วย

หมายเหตุ : หากคุณไม่ต้องการใช้คลาส IPAddress ใน. NET คุณสามารถแทนที่ด้วยเมธอดของฉันได้ นอกจากนี้ยังครอบคลุม IPv4 ที่แมปและกรณีพิเศษด้วยในขณะที่ IPAddress ไม่ครอบคลุม

class IPv6
{
    public List<string> FindIPv6InFile(string filePath)
    {
        Char ch;
        StringBuilder sbIPv6 = new StringBuilder();
        List<string> listIPv6 = new List<string>();
        StreamReader reader = new StreamReader(filePath);
        do
        {
            bool hasColon = false;
            int length = 0;

            do
            {
                ch = (char)reader.Read();

                if (IsEscapeChar(ch))
                    break;

                //Check the first 5 chars, if it has colon, then continue appending to stringbuilder
                if (!hasColon && length < 5)
                {
                    if (ch == ':')
                    {
                        hasColon = true;
                    }
                    sbIPv6.Append(ch.ToString());
                }
                else if (hasColon) //if no colon in first 5 chars, then dont append to stringbuilder
                {
                    sbIPv6.Append(ch.ToString());
                }

                length++;

            } while (!reader.EndOfStream);

            if (hasColon && !listIPv6.Contains(sbIPv6.ToString()) && IsIPv6(sbIPv6.ToString()))
            {
                listIPv6.Add(sbIPv6.ToString());
            }

            sbIPv6.Clear();

        } while (!reader.EndOfStream);
        reader.Close();
        reader.Dispose();

        return listIPv6;
    }

    public List<string> FindIPv6InText(string text)
    {
        StringBuilder sbIPv6 = new StringBuilder();
        List<string> listIPv6 = new List<string>();

        for (int i = 0; i < text.Length; i++)
        {
            bool hasColon = false;
            int length = 0;

            do
            {
                if (IsEscapeChar(text[length + i]))
                    break;

                //Check the first 5 chars, if it has colon, then continue appending to stringbuilder
                if (!hasColon && length < 5)
                {
                    if (text[length + i] == ':')
                    {
                        hasColon = true;
                    }
                    sbIPv6.Append(text[length + i].ToString());
                }
                else if (hasColon) //if no colon in first 5 chars, then dont append to stringbuilder
                {
                    sbIPv6.Append(text[length + i].ToString());
                }

                length++;

            } while (i + length != text.Length);

            if (hasColon && !listIPv6.Contains(sbIPv6.ToString()) && IsIPv6(sbIPv6.ToString()))
            {
                listIPv6.Add(sbIPv6.ToString());
            }

            i += length;
            sbIPv6.Clear();
        }

        return listIPv6;
    }

    bool IsEscapeChar(char ch)
    {
        if (ch != ' ' && ch != '\r' && ch != '\n' && ch!='\t')
        {
            return false;
        }

        return true;
    }

    bool IsIPv6(string maybeIPv6)
    {
        IPAddress ip;
        if (IPAddress.TryParse(maybeIPv6, out ip))
        {
            return ip.AddressFamily == AddressFamily.InterNetworkV6;
        }
        else
        {
            return false;
        }
    }

}

1

InetAddressUtilsมีการกำหนดรูปแบบทั้งหมด ฉันใช้รูปแบบโดยตรงและวางที่นี่เพื่ออ้างอิง:

private static final String IPV4_BASIC_PATTERN_STRING =
        "(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}" + // initial 3 fields, 0-255 followed by .
         "([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])"; // final field, 0-255

private static final Pattern IPV4_PATTERN =
    Pattern.compile("^" + IPV4_BASIC_PATTERN_STRING + "$");

private static final Pattern IPV4_MAPPED_IPV6_PATTERN = // TODO does not allow for redundant leading zeros
        Pattern.compile("^::[fF]{4}:" + IPV4_BASIC_PATTERN_STRING + "$");

private static final Pattern IPV6_STD_PATTERN =
    Pattern.compile(
            "^[0-9a-fA-F]{1,4}(:[0-9a-fA-F]{1,4}){7}$");

private static final Pattern IPV6_HEX_COMPRESSED_PATTERN =
    Pattern.compile(
            "^(([0-9A-Fa-f]{1,4}(:[0-9A-Fa-f]{1,4}){0,5})?)" + // 0-6 hex fields
             "::" +
             "(([0-9A-Fa-f]{1,4}(:[0-9A-Fa-f]{1,4}){0,5})?)$"); // 0-6 hex fields 

1

ใช้ Ruby? ลองสิ่งนี้:

/^(((?=.*(::))(?!.*\3.+\3))\3?|[\dA-F]{1,4}:)([\dA-F]{1,4}(\3|:\b)|\2){5}(([\dA-F]{1,4}(\3|:\b|$)|\2){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4})\z/i

1

ขึ้นอยู่กับความต้องการของคุณการประมาณเช่น:

[0-9a-f:]+

อาจจะเพียงพอ (เช่นเดียวกับการ grepping ไฟล์บันทึกอย่างง่าย)


0

สำหรับผู้ใช้ PHP 5.2+ ใช้filter_varงานได้ดี

ฉันรู้ว่านี่ไม่ได้ตอบคำถามเดิม (โดยเฉพาะวิธีแก้ปัญหา regex) แต่ฉันโพสต์สิ่งนี้ด้วยความหวังว่ามันอาจช่วยคนอื่นได้ในอนาคต

$is_ip4address = (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) !== FALSE);
$is_ip6address = (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) !== FALSE);

0

สิ่งนี้จะใช้ได้กับ IPv4 และ IPv6:

^(([0-9a-f]{0,4}:){1,7}[0-9a-f]{1,4}|([0-9]{1,3}\.){3}[0-9]{1,3})$

2
มันตรงกับที่อยู่ไม่ถูกต้องมี 2 ::กรณีของ เช่น2404:6800::4003:c02::8a
nhahtdh

ตรงกับ IPv4 ที่ไม่ถูกต้อง 666.666.666.666
Ryan Williams

0

นี่คือสิ่งที่ฉันคิดขึ้นโดยใช้กลุ่มผู้มองหาและตั้งชื่อ แน่นอนว่านี่เป็นเพียง IPv6 แต่ไม่ควรรบกวนรูปแบบเพิ่มเติมหากคุณต้องการเพิ่ม IPv4:

(?=([0-9a-f]+(:[0-9a-f])*)?(?P<wild>::)(?!([0-9a-f]+:)*:))(::)?([0-9a-f]{1,4}:{1,2}){0,6}(?(wild)[0-9a-f]{0,4}|[0-9a-f]{1,4}:[0-9a-f]{1,4})


0

เพียงจับคู่ท้องถิ่นจากแหล่งกำเนิดพร้อมวงเล็บเหลี่ยม ฉันรู้ว่ามันไม่ครอบคลุมเท่าที่ควร แต่ในจาวาสคริปต์คนอื่น ๆ มีปัญหาที่ยากในการติดตามปัญหาส่วนใหญ่ที่ใช้งานไม่ได้ดังนั้นสิ่งนี้ดูเหมือนจะทำให้ฉันได้สิ่งที่ฉันต้องการในตอนนี้ AF ตัวพิมพ์ใหญ่พิเศษก็ไม่จำเป็นเช่นกัน

^\[([0-9a-fA-F]{1,4})(\:{1,2})([0-9a-fA-F]{1,4})(\:{1,2})([0-9a-fA-F]{1,4})(\:{1,2})([0-9a-fA-F]{1,4})(\:{1,2})([0-9a-fA-F]{1,4})\]

เวอร์ชั่นของ Jinnko นั้นเรียบง่ายและดีกว่าที่ฉันเห็น


0

ตามที่ระบุไว้ข้างต้นอีกวิธีหนึ่งในการรับการตรวจสอบความถูกต้องของตัววิเคราะห์ข้อความ IPv6 คือการใช้การเขียนโปรแกรม นี่คือสิ่งที่สอดคล้องกับ RFC-4291 และ RFC-5952 อย่างสมบูรณ์ ฉันเขียนโค้ดนี้ใน ANSI C (ทำงานกับ GCC ผ่านการทดสอบบน Linux - ทำงานกับเสียงดังลั่นผ่านการทดสอบบน FreeBSD) ดังนั้นจึงอาศัยไลบรารีมาตรฐาน ANSI C เท่านั้นดังนั้นจึงสามารถรวบรวมได้ทุกที่ (ฉันเคยใช้สำหรับการแยกวิเคราะห์ IPv6 ภายในโมดูลเคอร์เนลด้วย FreeBSD)

// IPv6 textual representation validating parser fully compliant with RFC-4291 and RFC-5952
// BSD-licensed / Copyright 2015-2017 Alexandre Fenyo

#include <string.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>

typedef enum { false, true } bool;

static const char hexdigits[] = "0123456789abcdef";
static int digit2int(const char digit) {
  return strchr(hexdigits, digit) - hexdigits;
}

// This IPv6 address parser handles any valid textual representation according to RFC-4291 and RFC-5952.
// Other representations will return -1.
//
// note that str input parameter has been modified when the function call returns
//
// parse_ipv6(char *str, struct in6_addr *retaddr)
// parse textual representation of IPv6 addresses
// str:     input arg
// retaddr: output arg
int parse_ipv6(char *str, struct in6_addr *retaddr) {
  bool compressed_field_found = false;
  unsigned char *_retaddr = (unsigned char *) retaddr;
  char *_str = str;
  char *delim;

  bzero((void *) retaddr, sizeof(struct in6_addr));
  if (!strlen(str) || strchr(str, ':') == NULL || (str[0] == ':' && str[1] != ':') ||
      (strlen(str) >= 2 && str[strlen(str) - 1] == ':' && str[strlen(str) - 2] != ':')) return -1;

  // convert transitional to standard textual representation
  if (strchr(str, '.')) {
    int ipv4bytes[4];
    char *curp = strrchr(str, ':');
    if (curp == NULL) return -1;
    char *_curp = ++curp;
    int i;
    for (i = 0; i < 4; i++) {
      char *nextsep = strchr(_curp, '.');
      if (_curp[0] == '0' || (i < 3 && nextsep == NULL) || (i == 3 && nextsep != NULL)) return -1;
      if (nextsep != NULL) *nextsep = 0;
      int j;
      for (j = 0; j < strlen(_curp); j++) if (_curp[j] < '0' || _curp[j] > '9') return -1;
      if (strlen(_curp) > 3) return -1;
      const long val = strtol(_curp, NULL, 10);
      if (val < 0 || val > 255) return -1;
      ipv4bytes[i] = val;
      _curp = nextsep + 1;
    }
    sprintf(curp, "%x%02x:%x%02x", ipv4bytes[0], ipv4bytes[1], ipv4bytes[2], ipv4bytes[3]);
  }

  // parse standard textual representation
  do {
    if ((delim = strchr(_str, ':')) == _str || (delim == NULL && !strlen(_str))) {
      if (delim == str) _str++;
      else if (delim == NULL) return 0;
      else {
        if (compressed_field_found == true) return -1;
        if (delim == str + strlen(str) - 1 && _retaddr != (unsigned char *) (retaddr + 1)) return 0;
        compressed_field_found = true;
        _str++;
        int cnt = 0;
        char *__str;
        for (__str = _str; *__str; ) if (*(__str++) == ':') cnt++;
        unsigned char *__retaddr = - 2 * ++cnt + (unsigned char *) (retaddr + 1);
        if (__retaddr <= _retaddr) return -1;
        _retaddr = __retaddr;
      }
    } else {
      char hexnum[4] = "0000";
      if (delim == NULL) delim = str + strlen(str);
      if (delim - _str > 4) return -1;
      int i;
      for (i = 0; i < delim - _str; i++)
        if (!isxdigit(_str[i])) return -1;
        else hexnum[4 - (delim - _str) + i] = tolower(_str[i]);
      _str = delim + 1;
      *(_retaddr++) = (digit2int(hexnum[0]) << 4) + digit2int(hexnum[1]);
      *(_retaddr++) = (digit2int(hexnum[2]) << 4) + digit2int(hexnum[3]);
    }
  } while (_str < str + strlen(str));
  return 0;
}

-1

ลองซับขนาดเล็กนี้ ควรจับคู่เฉพาะที่อยู่ IPv6 ที่ไม่มีการบีบอัด / บีบอัดที่ถูกต้องเท่านั้น (ไม่มีลูกผสม IPv4)

/(?!.*::.*::)(?!.*:::.*)(?!:[a-f0-9])((([a-f0-9]{1,4})?[:](?!:)){7}|(?=(.*:[:a-f0-9]{1,4}::|^([:a-f0-9]{1,4})?::))(([a-f0-9]{1,4})?[:]{1,2}){1,6})[a-f0-9]{1,4}/

ที่จริงแล้วที่อยู่ IPv6 ที่ถูกต้องนั้นรวมถึงไฮบริดแบบไม่บีบอัดบีบอัดแบบไม่บีบอัดและไฮบริดแบบบีบอัด ต้องใช้เวลามากกว่าที่คุณต้องจับคู่การแสดงข้อความที่ถูกต้องของที่อยู่ IPv6 จริงๆ
Ron Maupin

-2

regex อนุญาตให้ใช้เลขศูนย์นำหน้าในส่วน IPv4

Unix และ Mac distros บางตัวจะแปลงส่วนเหล่านั้นเป็นฐานแปด

ฉันแนะนำให้ใช้25[0-5]|2[0-4]\d|1\d\d|[1-9]?\dเป็นเซ็กเมนต์ IPv4


-2

หากคุณต้องการเฉพาะ IP-s ปกติ (ไม่มีเครื่องหมายทับ) ที่นี่:

^(?:[0-9a-f]{1,4}(?:::)?){0,7}::[0-9a-f]+$

ฉันใช้มันเพื่อเน้นไวยากรณ์ของฉันในโปรแกรมแก้ไขไฟล์โฮสต์ ทำงานเป็นเสน่ห์


ไม่มีวิธีใดที่จะใช้งานได้อย่างเหมาะสมมันไม่สามารถจับคู่ที่อยู่ ipv6 เดียวที่มีเครื่องหมายจุดคู่เดียวในนั้นการจับคู่ทั้งหมดของคุณอยู่ในทวิภาคสองครั้งและคุณต้องการเครื่องหมายจุดคู่สำหรับกลุ่มสุดท้ายของคุณอย่างชัดเจนการสรุปสามารถเกิดขึ้นได้ทุกที่ .. ..
KillianDS

(?: [0-9a-f] {1,4} (? :::?)?) {0,7} ::? [0-9a-f] {1,4}
แฮร์รี่

ยังคงผิด แต่ถึงอย่างนั้นคุณจะต้องทำซ้ำคำตอบของ JinnKo ซึ่งดีพอสำหรับจุดประสงค์ง่ายๆ แต่ก็ยังมีข้อบกพร่อง (ไม่จับสรุปสองครั้งและไม่อนุญาตให้มีการตรวจสอบแบบจุดหรือ localhost หรือ :: termination,. .. )
KillianDS
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.