Biểu thức chính quy khớp với địa chỉ IPv6 hợp lệ


111

Tôi đang gặp sự cố khi viết một biểu thức chính quy khớp với các địa chỉ IPv6 hợp lệ, bao gồm cả những địa chỉ ở dạng nén của chúng (với ::hoặc số không ở đầu bị bỏ qua khỏi mỗi cặp byte).

Ai đó có thể đề xuất một biểu thức chính quy sẽ đáp ứng yêu cầu không?

Tôi đang xem xét việc mở rộng từng cặp byte và khớp kết quả với một regex đơn giản hơn.



Tôi đã thử tất cả các câu trả lời bên dưới và chúng không hoạt động cho tất cả các trường hợp thử nghiệm của tôi và / hoặc chúng cũng bao gồm IPv4 không được yêu cầu. Tôi nhận thấy đây là giải pháp sạch nhất cho đến nay: stackoverflow.com/a/21944928/3112803
gfrobenius 21/02

Câu trả lời:


252

Tôi không thể nhận được câu trả lời của @Factor Mystic để hoạt động với biểu thức chính quy POSIX, vì vậy tôi đã viết một câu trả lời hoạt động với biểu thức chính quy POSIX và biểu thức chính quy PERL.

Nó phải phù hợp với:

Biểu thức IPv6 Thông thường:

(([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]))

Để dễ đọc, sau đây là phần chia biểu thức chính quy ở trên tại các điểm OR chính thành các dòng riêng biệt:

# 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])

Để làm cho phần trên dễ hiểu hơn, mã "giả" sau đây sao chép phần trên:

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

Tôi đã đăng một tập lệnh trên GitHub để kiểm tra biểu thức chính quy: https://gist.github.com/syzdek/6086792


3
Bạn IPv4 regex không phù hợp với các khu công nghiệp như127.000.000.001
Kentzo

21
Phân đoạn IPv4 không được bao gồm các số 0 ở đầu. Nếu có số 0 ở đầu, thì phân đoạn IPv4 phải được diễn giải ở dạng bát phân. Vì vậy, IPV4SEG ở trên là chính xác khi không cho phép '000'. Tuy nhiên, nó cho phép '00' mà nó không nên.
par

3
Không hoạt động cho tôi trong trình duyệt như tôi mong đợi. Đã xác thực ngay cả reg.test ('3zzzzffe: 1900: 4545: 3: 200: f8ff: fe21: 67cf') rõ ràng không phải là địa chỉ IPv6 hợp lệ. Có nhiều kết quả tốt hơn với regex tại đây: nbviewer.ipython.org/github/rasbt/python_reference/blob/master/…
Capaj

7
ipv6 regex tuyệt vời. tìm thấy một lỗi nhỏ với phần liên kết cục bộ. bạn có fe80nơi nó phải được cái gì đó như [fF][eE]80một ffffmà nên là một cái gì đó giống như[fF]{4}
user2831628

4
+1 vì cho thấy rằng regexes có thể (theo cách giống như bất kỳ mã nguồn nào) thực sự có thể đọc được nếu bạn quan tâm và định dạng chúng.
Natix

52

Phần sau sẽ xác thực địa chỉ IPv4, IPv6 (đầy đủ và nén) và IPv6v4 (đầy đủ và nén):

'/^(?>(?>([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
Mặc dù việc xác thực ip-s có thể được thực hiện như Frank Krueger đề xuất, giải pháp này là giải pháp thực sự trả lời câu hỏi (mặc dù tôi chưa thử nghiệm đầy đủ) cũng như nếu bạn có nhiều IP mà bạn muốn kiểm tra theo cú pháp và có thể khớp với trong một dòng văn bản, bạn không thể sử dụng kỹ thuật xác thực IP.
Gyuri

Xin chào, tôi đã thử nghiệm RegExp này và không hiệu quả với tôi. Nó cho biết D là cờ không hợp lệ và khi tôi xóa nó, nó nói "SyntaxError: invalid quantifier"
diosney

3
JavaScript triển khai một tập hợp con các biểu thức chính quy kiểu Perl, không phải toàn bộ PCRE. Regex của tôi sẽ không hoạt động nếu không có một số tính năng nâng cao của PCRE.
MichaelRushton

2
Điều này mang lại ngoại lệ cho tôi trong C #
sarat

1
Trường hợp kiểm tra không thành công: FE80: 0000: 0000: 0000: 0202: B3FF: FE1E: 8329 Sử dụng phiên bản Elixir mới nhất vào ngày này, sử dụng PCRE bên dưới.
pmarreck

23

Có vẻ như bạn đang sử dụng Python. Nếu vậy, bạn có thể sử dụng một cái gì đó như sau:

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

Tôi không nghĩ rằng bạn phải có IPv6 được biên dịch sang Python để có được inet_pton, điều này cũng có thể phân tích cú pháp địa chỉ IPv4 nếu bạn chuyển vào socket.AF_INETlàm tham số đầu tiên. Lưu ý: điều này có thể không hoạt động trên các hệ thống không phải Unix.


4
Bạn nên chỉ định loại ngoại lệ trong exceptmệnh đề. Nếu không, exceptsẽ bắt mọi thứ và có thể che dấu các lỗi không liên quan. Loại ở đây nên được socket.error.
Ayman Hourieh

A) inet_pton không ném ra các ngoại lệ khác, trừ khi tài liệu sai, và B) ngay cả khi điều đó xảy ra, bạn sẽ trả lại điều gì khác ngoài Sai?
Joe Hildebrand

2
Re: các lỗi khác ... nếu người dùng chuyển vào một chuỗi không phải là chuỗi, TypeError sẽ bị ăn. Rõ ràng là một danh sách không phải là ipv6, nhưng tôi có thể muốn có nó cá chép mà tôi đã chuyển sai loại.
Gregg Lind

1
+1 Điều này đã giúp tôi rất nhiều. Một số điểm bổ sung cần được thêm vào: 1) socket.inet_pton có thể được sử dụng để kiểm tra tính hợp lệ của cả hai họ địa chỉ IP (IP và IPv6). 2) Tài liệu ở đây ( docs.python.org/2/library/socket.html ) gợi ý rằng tài liệu này có sẵn trên nền tảng Unix. Nó có thể không có sẵn trên nền tảng Win.
mkoistinen

bằng cách sử dụng django và điều này sẽ giúp!
elad silver

23

Từ " 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
Biểu thức chính quy như thế này phải là một "mùi mã" mà có lẽ biểu thức chính quy không phải là giải pháp phù hợp nhất ở đây. (Mặc dù, tôi đoán op đã yêu cầu nó ...)
Thanatos

10
@ user712092 - tất cả những ai đã từng thấy một cơ sở mã có những điểm chướng mắt như vậy
danielpops

2
Đây là một việc hoàn toàn không cần thiết đối với REs. Chương trình tạo ra nó không hiểu nó đang làm gì. Một con người sẽ không bao giờ làm theo cách này. Đừng để bị lừa bởi sự phức tạp rõ ràng - RE thực sự là "ma thuật đen" đối với nhiều người, nhưng không có lý do gì để đặt chúng trên một hành tinh khác!
Chuck Kollars

1 nhưng OMG có phải là một cách tốt hơn để làm điều này: P Để tham khảo: ví Rails sức trợ giúp này: stackoverflow.com/questions/16965697/...
Tilo

1
Nó thực sự là một mùi mã; tuy nhiên sau khi xem xét, bạn sẽ thấy rằng mỗi regex khá ngắn gọn. Vấn đề là có các mẫu khác nhau được tạo ra bởi 'nén' của ipv6 - Dấu hai chấm bắt đầu, giữa và cuối, ngoài ra, nếu bạn đã sử dụng dấu hai chấm, bạn không thể sử dụng lại, trên tổng số dấu hai chấm trước và sau dấu đôi phải cộng lại. Perl 6 thể giải quyết được vấn đề này, nhưng nó không nằm ngoài cú pháp PCRE. (PS - Tôi không đếm nhúng ipv4 ở cuối, mà là dài hơn phần ipv6!)
Gerard ONeill

11

Tôi phải chấp nhận mạnh mẽ câu trả lời từ Frank Krueger .

Trong khi bạn nói rằng bạn cần một biểu thức chính quy để khớp với địa chỉ IPv6, tôi cho rằng điều bạn thực sự cần là có thể kiểm tra xem một chuỗi đã cho có phải là địa chỉ IPv6 hợp lệ hay không. Có một sự khác biệt tinh tế nhưng quan trọng ở đây.

Có nhiều cách để kiểm tra xem một chuỗi đã cho có phải là địa chỉ IPv6 hợp lệ hay không và đối sánh biểu thức chính quy chỉ là một giải pháp.

Sử dụng thư viện hiện có nếu bạn có thể. Thư viện sẽ có ít lỗi hơn và việc sử dụng nó sẽ dẫn đến việc bạn phải duy trì ít mã hơn.

Biểu thức chính quy được đề xuất bởi Factor Mystic là dài và phức tạp. Nó rất có thể hoạt động, nhưng bạn cũng nên xem xét cách bạn đối phó nếu nó bất ngờ thất bại. Điểm tôi đang cố gắng đưa ra ở đây là nếu bạn không thể tự mình tạo biểu thức chính quy bắt buộc, bạn sẽ không thể dễ dàng gỡ lỗi nó.

Nếu bạn không có thư viện phù hợp, tốt hơn là bạn nên viết quy trình xác thực IPv6 của riêng mình mà không phụ thuộc vào biểu thức chính quy. Nếu bạn viết nó, bạn hiểu nó và nếu bạn hiểu nó, bạn có thể thêm nhận xét để giải thích nó để những người khác cũng có thể hiểu và sau đó duy trì nó.

Hãy thận trọng khi sử dụng biểu thức chính quy có chức năng mà bạn không thể giải thích cho người khác.


1
Sử dụng hai biểu thức chính quy, một biểu thức tự do và một biểu thức ngoại lệ để bẫy các địa chỉ không hợp lệ được cho phép bởi biểu thức đầu tiên, có thể dễ dàng hơn một biểu thức ( return ex1.match(S) && ! ex2.match(S)).
Raedwald

4
Bạn đang giả định rằng anh ta đang xác thực các IP riêng lẻ khi anh ta gần như chắc chắn đang tìm kiếm các IP trong một khối văn bản lớn.
Navin

8

Tôi không phải là chuyên gia Ipv6 nhưng tôi nghĩ bạn có thể có được kết quả khá tốt dễ dàng hơn với kết quả này:

^([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})$

để trả lời "là một ipv6 hợp lệ" nó trông giống như ok đối với tôi. Để chia nhỏ nó thành nhiều phần ... hãy quên nó đi. Tôi đã bỏ qua địa chỉ không xác định (: :) vì không sử dụng "địa chỉ không xác định" trong cơ sở dữ liệu của tôi.

phần đầu: ^([0-9A-Fa-f]{0,4}:){2,7}<- khớp với phần có thể nén được, chúng ta có thể dịch điều này là: từ 2 đến 7 dấu hai chấm có thể có số thập phân giữa chúng.

theo sau là: [0-9A-Fa-f]{1,4}$<- một số thập lục phân (bỏ qua số 0 ở đầu) HOẶC ((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.|$)){4}<- một địa chỉ Ipv4


1
+1 vì thực sự bám sát câu hỏi OP và trình bày một bản regex tương đối đẹp mắt và phần nào hoạt động.
xebeche

1
Điều này không khớp với ":: 1"
lsalamon

Huh? Trong java regex syntaxt, nó khớp:start() = 0, end() = 3 group(0) = "::1" group(1) = ":" group(2) = "1" group(3) = "null" group(4) = "null" group(5) = "null"
Remi Morin

Ở đâu đó, ai đó thông báo cho tôi về sự cố với regex của tôi, phần nén "::" chỉ có thể xuất hiện một lần. Vì vậy, ":: 1 :: 2" sẽ khớp với regex của tôi nhưng nó không phải là IPV6 hợp lệ. Một regex thứ hai có thể xác nhận trường hợp này. Đề xuất đầy đủ là sử dụng trình phân tích cú pháp trạng thái để xác thực. Tôi đồng ý rằng mã kết quả sẽ dễ đọc và dễ bảo trì hơn (và ai đó có thể đã mã hóa nó trong một nguồn mở ở đâu đó).
Remi Morin

8

Điều này cũng bắt các địa chỉ loopback (:: 1) và ipv6. đã thay đổi {} thành + và đặt: bên trong dấu ngoặc vuông đầu tiên.

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

đã thử nghiệm với đầu ra ifconfig -a http://regexr.com/

Tùy chọn o tùy chọn đầu cuối Unix hoặc Mac OSx chỉ trả về đầu ra phù hợp (ipv6) bao gồm :: 1

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

Nhận Tất cả địa chỉ IP (IPv4 HOẶC IPv6) và in khớp trên thuật ngữ OSx unix

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]+)'

Tôi thích sự đơn giản. Điều này cuối cùng làm việc cho tôi:ip a | grep -Po '[\w:]+:+[\w:]+'
Noam Manos

Hài hước được đánh giá cao!
Soumya Kanti

Khi tôi chạy ipconfig / all, địa chỉ ip của tôi kết thúc bằng% 10, biểu thức này không khớp với phần này?
Peter

7

Biểu thức chính quy này sẽ khớp với các địa chỉ IPv6 và IPv4 hợp lệ phù hợp với việc triển khai GNU C ++ của regex với chế độ MỞ RỘNG THƯỜNG XUYÊN được sử dụng:

"^\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

Hãy coi chừng! Trong Java, việc sử dụng InetAddress và các lớp liên quan (Inet4Address, Inet6Address, URL) có thể liên quan đến trafic mạng! Ví dụ: phân giải DNS (URL.equals, InetAddress từ chuỗi!). Cuộc gọi này có thể mất nhiều thời gian và đang bị chặn!

Đối với IPv6, tôi có một cái gì đó như thế này. Tất nhiên, điều này không xử lý các chi tiết rất tinh vi của IPv6 như chỉ số vùng chỉ được phép trên một số lớp địa chỉ IPv6. Và regex này không được viết để chụp theo nhóm, nó chỉ là một loại regexp "khớp".

S - Phân đoạn 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})

Sơ đồ (phần đầu đối sánh địa chỉ IPv6 với hậu tố IPv4, phần thứ hai khớp với địa chỉ IPv6, phần cuối là chỉ mục vùng):

(
(
::(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]+)?

Và đây có thể là regex (không phân biệt chữ hoa chữ thường, bao quanh những thứ cần thiết như đầu / cuối dòng, v.v.):

(?:
(?:
::(?:[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

Sau regex chỉ dành cho IPv6. Nhóm 1 đấu với IP.

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

+1 Không nhất thiết phải luôn có một regex siêu phức tạp hoàn hảo mà con người không thể hiểu được. Tôi sẽ sử dụng cái này vì tôi hiểu nó hoạt động gì và trong trường hợp của tôi, tôi có thể chắc chắn rằng nếu tôi nhận được thứ gì đó giống với ipv6 hợp lệ, thì đó là ipv6 hợp lệ.
David L.

3
điều này sẽ không khớp nói: fe80 :: 1 hoặc 2342: 32fd :: 2d32
James

3

Một regex đơn giản sẽ phù hợp, nhưng tôi không khuyên bạn nên xác thực theo bất kỳ loại nào là:

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

Lưu ý rằng điều này phù hợp với nén ở bất kỳ đâu trong địa chỉ, mặc dù nó sẽ không khớp với địa chỉ lặp lại :: 1. Tôi thấy đây là một thỏa hiệp hợp lý để giữ cho regex đơn giản.

Tôi sử dụng thành công điều này trong các quy tắc lựa chọn thông minh iTerm2 để nhấp bốn lần vào địa chỉ IPv6.


3
Ý bạn là A-F, không phải A-Z! Cũng lưu ý rằng bạn đang loại trừ ký hiệu tứ phân chấm.
xebeche

3

Nếu bạn sử dụng Perl, hãy thử 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);

Xác thực :: IP

use Validate::IP qw'is_ipv6';

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


2

Trong Scala, sử dụng trình xác nhận Apache Commons nổi tiếng.

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)

Sau thử nghiệm của phương pháp 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
  }
}

Thật thú vị, Nó tuyên bố kiểm tra xem đó có phải là địa chỉ hợp lệ hay không, " Xác thực nếu ip được chuyển là địa chỉ IPv4 hoặc IPv6 hợp lệ. ", Nhưng nó thực sự chỉ kiểm tra xem nó có được định dạng là địa chỉ hợp lệ hay không. Ví dụ: 1200:0000:AB00:1234:0000:2552:7777:1313là định dạng hợp lệ cho địa chỉ IPv6, nhưng nó không phải là địa chỉ IPv6 hợp lệ khi phương thức kiểm tra trả về. Tôi cá rằng nó nghĩ 241.54.113.65là một địa chỉ IPv4 hợp lệ.
Ron Maupin

2

Nhìn vào các mẫu có trong các câu trả lời khác, có một số mẫu hay có thể được cải thiện bằng cách tham khảo các nhóm và sử dụng các lookahead. Đây là một ví dụ về một mẫu tự tham chiếu mà tôi sẽ sử dụng trong PHP nếu tôi phải:

^(?<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))$

Lưu ý: PHP có một bộ lọc tích hợp cho điều này sẽ là một giải pháp tốt hơn mẫu này.

Phân tích Regex101


2

Tôi đã tạo phần sau bằng python và hoạt động với mô-đun re. Các xác nhận nhìn về phía trước đảm bảo rằng số lượng dấu chấm hoặc dấu hai chấm chính xác xuất hiện trong địa chỉ. Nó không hỗ trợ IPv4 trong ký hiệu 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 cho ipv6 có thể thực sự khó khăn khi bạn xem xét các địa chỉ có ipv4 nhúng và các địa chỉ được nén, như bạn có thể thấy từ một số câu trả lời sau.

Thư viện IPAddress Java mã nguồn mở sẽ xác thực tất cả các biểu diễn tiêu chuẩn của IPv6 và IPv4 và cũng hỗ trợ độ dài tiền tố (và xác thực như vậy). Tuyên bố từ chối trách nhiệm: Tôi là người quản lý dự án của thư viện đó.

Ví dụ về mã:

        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

Trong Java, bạn có thể sử dụng lớp thư viện sun.net.util.IPAddressUtil:

IPAddressUtil.isIPv6LiteralAddress(iPaddress);

3
sun.net. * là API riêng.
David Kocher

1

Rất khó để tìm thấy một biểu thức chính quy hoạt động cho tất cả các trường hợp IPv6. Chúng thường khó bảo trì, không dễ đọc và có thể gây ra các vấn đề về hiệu suất. Do đó, tôi muốn chia sẻ một giải pháp thay thế mà tôi đã phát triển: Biểu thức chính quy (RegEx) cho IPv6 Tách biệt khỏi IPv4

Bây giờ bạn có thể hỏi rằng "Phương pháp này chỉ tìm thấy IPv6, làm thế nào tôi có thể tìm thấy IPv6 trong văn bản hoặc tệp?" Dưới đây là các phương pháp cho vấn đề này.

Lưu ý : Nếu bạn không muốn sử dụng lớp IPAddress trong .NET, bạn cũng có thể thay thế nó bằng phương thức của tôi . Nó cũng bao gồm IPv4 được ánh xạ và các trường hợp đặc biệt, trong khi IPAddress không bao gồm.

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đã xác định tất cả các mẫu. Tôi đã kết thúc bằng cách sử dụng trực tiếp mẫu của họ và đang dán nó ở đây để tham khảo:

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

Sử dụng Ruby? Thử cái này:

/^(((?=.*(::))(?!.*\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

Tùy thuộc vào nhu cầu của bạn, ước tính như:

[0-9a-f:]+

có thể là đủ (ví dụ như với việc thu thập tệp nhật ký đơn giản.)


0

Đối với người dùng PHP 5.2+ filter_varhoạt động tốt.

Tôi biết điều này không trả lời câu hỏi ban đầu (cụ thể là một giải pháp regex), nhưng tôi đăng bài này với hy vọng nó có thể giúp ích cho người khác trong tương lai.

$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

Điều này sẽ hoạt động cho IPv4 và IPv6:

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

2
Nó khớp các địa chỉ không hợp lệ với 2 trường hợp của ::. ví dụ2404:6800::4003:c02::8a
nhahtdh

khớp với IPv4 666.666.666.666 không hợp lệ
Ryan Williams

0

Đây là những gì tôi đã nghĩ ra, sử dụng một chút tìm kiếm và các nhóm được đặt tên. Tất nhiên đây chỉ là IPv6, nhưng nó sẽ không ảnh hưởng đến các mẫu bổ sung nếu bạn muốn thêm 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

Bạn có thể sử dụng các công cụ shell ipextract mà tôi đã tạo cho mục đích này. Chúng dựa trên regexp và grep.

Sử dụng:

$ ifconfig | ipextract6
fe80::1%lo0
::1
fe80::7ed1:c3ff:feec:dee1%en0

0

Chỉ so khớp các từ địa phương từ một nguồn gốc có bao gồm dấu ngoặc vuông. Tôi biết nó không toàn diện nhưng trong javascript, những cái khác gặp khó khăn trong việc theo dõi các vấn đề chủ yếu là không hoạt động, vì vậy điều này dường như giúp tôi có được những gì tôi cần. AF viết hoa phụ cũng không cần thiết.

^\[([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})\]

Phiên bản của Jinnko được đơn giản hóa và tôi thấy tốt hơn.


0

Như đã nêu ở trên, một cách khác để có được trình phân tích cú pháp xác thực biểu diễn văn bản IPv6 là sử dụng lập trình. Đây là một trong những hoàn toàn phù hợp với RFC-4291 và RFC-5952. Tôi đã viết mã này bằng ANSI C (hoạt động với GCC, đã vượt qua các bài kiểm tra trên Linux - hoạt động với tiếng kêu, đã vượt qua các bài kiểm tra trên FreeBSD). Do đó, nó chỉ dựa vào thư viện chuẩn ANSI C, vì vậy nó có thể được biên dịch ở mọi nơi (tôi đã sử dụng nó để phân tích cú pháp IPv6 bên trong một mô-đun hạt nhân với 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

Hãy thử một lớp lót nhỏ này. Nó chỉ nên khớp với các địa chỉ IPv6 không nén / nén hợp lệ (không có IPv4 lai)

/(?!.*::.*::)(?!.*:::.*)(?!:[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}/

Trên thực tế, các địa chỉ IPv6 hợp lệ bao gồm kết hợp không nén, nén, không nén-kết hợp và nén. Nó thực sự mất nhiều hơn những gì bạn phải thực sự khớp với bất kỳ biểu diễn văn bản hợp lệ nào của địa chỉ IPv6.
Ron Maupin

-2

Regex cho phép sử dụng các số 0 ở đầu trong các phần IPv4.

Một số phân phối Unix và Mac chuyển đổi các phân đoạn đó thành số bát phân.

Tôi đề nghị sử dụng 25[0-5]|2[0-4]\d|1\d\d|[1-9]?\dlàm phân đoạn IPv4.


-2

Nếu bạn chỉ muốn IP-s bình thường (không có dấu gạch chéo), tại đây:

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

Tôi sử dụng nó cho công cụ đánh dấu cú pháp của mình trong ứng dụng chỉnh sửa tệp máy chủ. Hoạt động như một sự quyến rũ.


Không có cách nào mà điều này luôn hoạt động hiệu quả, nó không thể khớp một địa chỉ ipv6 với một dấu hai chấm duy nhất trong đó, tất cả các kết quả phù hợp của bạn đều nằm trên dấu hai chấm kép và bạn yêu cầu rõ ràng dấu hai chấm cho nhóm cuối cùng của mình, việc tóm tắt có thể xảy ra ở bất kỳ đâu .. .
KillianDS

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

Vẫn sai, nhưng thậm chí sau đó bạn sẽ phải lặp lại câu trả lời của JinnKo, câu trả lời này đủ tốt cho các mục đích đơn giản, nhưng vẫn có sai sót (không tóm tắt kép và không cho phép các quads có dấu chấm, cũng không phải localhost, nor :: end ,. ..)
KillianDS
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.