유효한 IPv6 주소와 일치하는 정규식
압축 된 형식의 주소를 포함하여 유효한 IPv6 주소와 일치하는 정규 표현식을 작성하는 데 문제가 ::
있습니다 (각 바이트 쌍에서 0이 생략되거나 선행됩니다).
누군가 요구 사항을 충족시키는 정규식을 제안 할 수 있습니까?
각 바이트 쌍을 확장하고 결과를 더 간단한 정규식과 일치시키는 것을 고려하고 있습니다.
POSIX 정규 표현식으로 작업하기 위해 @Factor Mystic의 답변을 얻을 수 없으므로 POSIX 정규 표현식 및 PERL 정규 표현식으로 작동하는 답변을 작성했습니다.
일치해야합니다.
- IPv6 주소
- 압축 된 IPv6 주소 없음 ( rfc5952의 섹션 2.2 )
- 영역 인덱스가있는 링크 로컬 IPv6 주소 ( rfc4007의 섹션 11 )
- IPv4 내장 IPv6 주소 ( rfc6052의 섹션 2 )
- IPv4 매핑 IPv6 주소 ( rfc2765의 섹션 2.1 )
- IPv4로 변환 된 주소 ( rfc2765의 섹션 2.1 )
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]))
읽기 쉽도록 다음은 위의 정규 표현식이 주요 OR 포인트에서 개별 라인으로 분할 된 것입니다.
# 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
다음은 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'
" IPv6 정규식 "에서 :
(\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)
파이썬을 사용하고있는 것 같습니다. 그렇다면 다음과 같이 사용할 수 있습니다.
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
을 얻기 위해 Python으로 IPv6을 컴파일해야한다고 생각하지 않습니다 . 첫 번째 매개 변수로 inet_pton
전달하면 IPv4 주소를 구문 분석 할 수도 있습니다 socket.AF_INET
. 참고 : Unix 이외의 시스템에서는 작동하지 않을 수 있습니다.
Frank Krueger 의 답변을 강력히 준수해야 합니다.
IPv6 주소와 일치하는 정규식이 필요하다고 말하면서 주어진 문자열이 유효한 IPv6 주소인지 확인할 수 있다고 가정합니다. 여기에는 미묘하지만 중요한 차이점이 있습니다.
주어진 문자열이 유효한 IPv6 주소이고 정규식 일치가 하나의 솔루션인지 확인하는 방법은 여러 가지가 있습니다.
가능하면 기존 라이브러리를 사용하십시오. 라이브러리에는 버그가 적고 유지 관리에 필요한 코드가 줄어 듭니다.
Factor Mystic 이 제안한 정규식 은 길고 복잡합니다. 아마도 효과가 있을지 모르지만 예기치 않게 실패 할 경우 어떻게 대처할 것인지 고려해야합니다. 내가 여기에서하려고하는 요점은 필요한 정규 표현식을 직접 만들 수 없다면 쉽게 디버깅 할 수 없다는 것입니다.
적합한 라이브러리가없는 경우 정규식에 의존하지 않는 고유 한 IPv6 유효성 검사 루틴을 작성하는 것이 좋습니다. 당신이 그것을 작성하면 그것을 이해하고 그것을 이해한다면 당신은 다른 사람들도 그것을 이해하고 계속 유지할 수 있도록 설명을 추가 할 수 있습니다.
다른 사람에게 설명 할 수없는 기능을 가진 정규식을 사용할 때는주의해서 행동하십시오.
나는 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 사이의 콜론은 16 진수 사이에있을 수 있습니다.
다음 : [0-9A-Fa-f]{1,4}$
<- 16 진수 (0 선도 생략) OR ((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.|$)){4}
"-는 IPv4 ADRESS
이 정규식은 사용 된 REGULAR EXTENDED 모드를 사용하여 정규 표현식의 GNU C ++ 구현에 따라 유효한 IPv6 및 IPv4 주소와 일치합니다.
"^\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*$"
조심해! Java에서 InetAddress 및 관련 클래스 (Inet4Address, Inet6Address, URL)를 사용하면 네트워크 트래픽이 발생할 수 있습니다! 예를 들어 DNS 확인 (URL.equals, InetAddress from string!). 통화 시간이 오래 걸리고 차단 중입니다!
IPv6의 경우 이와 같은 것이 있습니다. 물론 이것은 영역 인덱스가 일부 클래스의 IPv6 주소에서만 허용되는 것과 같이 IPv6의 매우 미묘한 세부 사항은 처리하지 않습니다. 이 정규식은 그룹 캡처 용으로 작성된 것이 아니라 정규식의 "일치하는"종류입니다.
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})
회로도 (첫 번째 부분은 IPv4 접미사와 IPv6 주소를 일치시키고, 두 번째 부분은 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]+)?
그리고 여기 정규식 (대소 문자를 구분하지 않고 줄의 시작 / 끝과 같이 필요한 것으로 서라운드) :
(?:
(?:
::(?:[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]+)?
이것은 루프백 (:: 1)과 ipv6 주소를 잡습니다. {}를 +로 변경하고 첫 번째 대괄호 안에 넣습니다.
([A-f0-9:]+:+)+[A-f0-9]+
ifconfig -a 출력 http://regexr.com/으로 테스트했습니다.
Unix 또는 Mac OSx 터미널 o 옵션은 :: 1을 포함하여 일치하는 출력 (ipv6) 만 반환합니다.
ifconfig -a | egrep -o '([A-f0-9:]+:+)+[A-f0-9]+'
모든 IP 주소 (IPv4 또는 IPv6)를 가져오고 유닉스 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]+)'
일치하는 간단한 정규식이지만 모든 종류의 유효성 검사에는 권장하지 않습니다.
([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}
루프백 주소 :: 1과 일치하지는 않지만 주소의 어느 곳에서나 압축과 일치합니다. 정규식을 단순하게 유지하기 위해 이것이 합리적인 타협을 찾습니다.
iTerm2 스마트 선택 규칙 에서이를 성공적으로 사용하여 IPv6 주소를 쿼드 클릭합니다.
Perl을 사용하는 경우 Net :: IPv6Addr을 사용하십시오.
use Net::IPv6Addr;
if( defined Net::IPv6Addr::is_ipv6($ip_address) ){
print "Looks like an ipv6 address\n";
}
use NetAddr::IP;
my $obj = NetAddr::IP->new6($ip_address);
use Validate::IP qw'is_ipv6';
if( is_ipv6($ip_address) ){
print "Looks like an ipv6 address\n";
}
에서 스칼라 잘 알려진 아파치 코 몬즈 유효성 검사기를 사용합니다.
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
}
}
다음 정규식은 IPv6 전용입니다. 그룹 1은 IP와 일치합니다.
(([0-9a-fA-F]{0,4}:){1,7}[0-9a-fA-F]{0,4})
모든 IPv6 사례에 적합한 정규식을 찾기가 어렵습니다. 일반적으로 유지 관리가 어렵고 쉽게 읽을 수 없으며 성능 문제가 발생할 수 있습니다. 따라서 필자가 개발 한 대체 솔루션을 공유하고 싶습니다. IPv6 용 정규식 (RegEx) IPv4와 분리
"이 방법은 IPv6 만 찾습니다. 텍스트 나 파일에서 IPv6을 어떻게 찾을 수 있습니까?" 이 문제에 대한 방법도 있습니다.
참고 : .NET에서 IPAddress 클래스를 사용하지 않으려는 경우 내 메소드로 바꿀 수도 있습니다 . IPAddress는 다루지 않지만 매핑 된 IPv4 및 특수한 경우도 다루고 있습니다.
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;
}
}
}
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
다른 답변에 포함 된 패턴을 보면 그룹을 참조하고 미리보기를 활용하여 개선 할 수있는 여러 가지 좋은 패턴이 있습니다. 다음은 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에는이를위한 필터가 내장되어있어이 패턴보다 더 나은 솔루션입니다.
루비를 사용하십니까? 이 시도:
/^(((?=.*(::))(?!.*\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
필요에 따라 다음과 같은 근사치가 있습니다.
[0-9a-f:]+
충분할 수 있습니다 (예 : 간단한 로그 파일 그 리핑과 같이).
Java에서는 라이브러리 클래스를 사용할 수 있습니다 sun.net.util.IPAddressUtil
.
IPAddressUtil.isIPv6LiteralAddress(iPaddress);
PHP 5.2+ 사용자 filter_var
는 훌륭하게 작동합니다.
나는 이것이 원래의 질문 (특히 정규식 솔루션)에 대한 답변이 아니라는 것을 알고 있지만 나중에 다른 사람을 도울 수 있기를 희망하여 이것을 게시합니다.
$is_ip4address = (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) !== FALSE);
$is_ip6address = (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) !== FALSE);
이것은 IPv4 및 IPv6에서 작동합니다.
^(([0-9a-f]{0,4}:){1,7}[0-9a-f]{1,4}|([0-9]{1,3}\.){3}[0-9]{1,3})$
여기에 약간의 미리보기와 명명 된 그룹을 사용하여 생각해 냈습니다. 이것은 물론 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})
이 목적으로 만든 ipextract 쉘 도구를 사용할 수 있습니다 . 그들은 정규 표현식과 grep을 기반으로합니다.
용법:
$ ifconfig | ipextract6
fe80::1%lo0
::1
fe80::7ed1:c3ff:feec:dee1%en0
파이썬을 사용하여 다음을 생성하고 re 모듈과 함께 작동합니다. 미리보기 어설 션을 사용하면 주소에 올바른 수의 점 또는 콜론이 표시됩니다. IPv6 표기법에서 IPv4를 지원하지 않습니다.
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)
대괄호가 포함 된 원점의 로컬 항목과 일치합니다. 나는 그것이 포괄적이지 않다는 것을 알고 있지만 자바 스크립트에서는 다른 것들이 주로 작동하지 않는 문제를 추적하기가 어려워서 지금 당장 필요한 것을 얻는 것처럼 보입니다. 여분의 수도 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의 버전은 간단하고 더 좋습니다.
위에서 언급했듯이 IPv6 텍스트 표현 검증 파서 를 얻는 또 다른 방법 은 프로그래밍을 사용하는 것입니다. 다음은 RFC-4291 및 RFC-5952를 완전히 준수하는 것입니다. 이 코드를 ANSI C로 작성했습니다 (GCC와 함께 작동, Linux에서 테스트 통과-clang과 함께 작동, FreeBSD에서 테스트 통과). 따라서 ANSI C 표준 라이브러리에만 의존하므로 어디에서나 컴파일 할 수 있습니다 (FreeBSD가있는 커널 모듈 내부에서 IPv6 구문 분석에 사용했습니다).
// 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;
}
ipv6에 대한 정규식은 ipv4가 포함 된 주소와 압축 된 주소를 고려할 때 정말 까다로울 수 있습니다. 이러한 답변 중 일부에서 볼 수 있습니다.
공개 소스 IPAddress Java 라이브러리 는 IPv6 및 IPv4의 모든 표준 표현을 검증하고 접두사 길이 (및 그러한 검증)도 지원합니다. 면책 조항 : 나는 그 도서관의 프로젝트 관리자입니다.
코드 예 :
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
}
이 작은 원 라이너를 사용해보십시오. 유효한 비 압축 / 압축 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}/
정규식을 사용하면 IPv4 부분에서 선행 0을 사용할 수 있습니다.
일부 Unix 및 Mac 배포판은 해당 세그먼트를 8 진수로 변환합니다.
25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d
IPv4 세그먼트로 사용 하는 것이 좋습니다 .
일반 IP 만 원한다면 (슬래시 없음), 여기 :
^(?:[0-9a-f]{1,4}(?:::)?){0,7}::[0-9a-f]+$
호스트 파일 편집기 응용 프로그램에서 구문 형광펜으로 사용합니다. 매력으로 작동합니다.
참고 URL : https://stackoverflow.com/questions/53497/regular-expression-that-matches-valid-ipv6-addresses
'programing tip' 카테고리의 다른 글
안드로이드 디렉토리에 파일을 나열하는 방법? (0) | 2020.07.26 |
---|---|
DataTable : 항목 표시 드롭 다운을 숨기고 검색 상자는 유지 (0) | 2020.07.26 |
Vim에서 f 및 t 명령은 무엇을합니까? (0) | 2020.07.26 |
DIV 대신 테이블 (0) | 2020.07.26 |
PHP 공지를 끄려면 어떻게합니까? (0) | 2020.07.26 |