압축 된 형식의 주소를 포함하여 유효한 IPv6 주소와 일치하는 정규식을 작성하는 데 문제가 ::
있습니다 (각 바이트 쌍에서 생략되거나 선행 0이 생략 됨).
누군가가 요구 사항을 충족하는 정규식을 제안 할 수 있습니까?
각 바이트 쌍을 확장하고 결과를 더 간단한 정규식과 일치시키는 것을 고려하고 있습니다.
압축 된 형식의 주소를 포함하여 유효한 IPv6 주소와 일치하는 정규식을 작성하는 데 문제가 ::
있습니다 (각 바이트 쌍에서 생략되거나 선행 0이 생략 됨).
누군가가 요구 사항을 충족하는 정규식을 제안 할 수 있습니까?
각 바이트 쌍을 확장하고 결과를 더 간단한 정규식과 일치시키는 것을 고려하고 있습니다.
답변:
@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]))
쉽게 읽을 수 있도록 다음은 주요 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
127.000.000.001
fe80
이 같은 있어야 할 곳에 [fF][eE]80
와 ffff
같은해야 뭔가[fF]{4}
다음은 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'
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
첫 번째 매개 변수로 inet_pton
전달하면 IPv4 주소를 구문 분석 할 수있는를 얻기 위해 IPv6을 Python으로 컴파일 할 필요가 없다고 생각합니다 socket.AF_INET
. 참고 : Unix가 아닌 시스템에서는 작동하지 않을 수 있습니다.
except
절에 예외 유형을 지정해야합니다 . 그렇지 않으면 except
모든 것을 포착하고 관련없는 오류를 가릴 수 있습니다. 여기의 유형은이어야합니다 socket.error
.
" 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)
나는 Frank Krueger 의 대답을 강력하게 두 번째로해야 할 것 입니다.
IPv6 주소와 일치하기 위해 정규식이 필요하다고 말했지만 실제로 필요한 것은 주어진 문자열이 유효한 IPv6 주소인지 확인할 수있는 것이라고 가정합니다. 여기에는 미묘하지만 중요한 차이점이 있습니다.
주어진 문자열이 유효한 IPv6 주소이고 정규식 일치가 유일한 솔루션인지 확인하는 방법은 여러 가지가 있습니다.
가능하면 기존 라이브러리를 사용하십시오. 라이브러리에는 버그가 적고이를 사용하면 유지 관리 할 코드가 줄어 듭니다.
Factor Mystic 이 제안한 정규식 은 길고 복잡합니다. 작동 할 가능성이 높지만 예기치 않게 실패 할 경우 대처 방법도 고려해야합니다. 여기서 제가하려는 요점은 필요한 정규식을 직접 구성 할 수 없으면 쉽게 디버그 할 수 없다는 것입니다.
적합한 라이브러리가없는 경우 정규식에 의존하지 않는 고유 한 IPv6 유효성 검사 루틴을 작성하는 것이 더 나을 수 있습니다. 당신이 그것을 쓰면 당신은 그것을 이해하고 당신이 그것을 이해한다면 다른 사람들도 그것을 이해하고 나중에 유지할 수 있도록 그것을 설명하는 주석을 추가 할 수 있습니다.
다른 사람에게 설명 할 수없는 기능을 가진 정규 표현식을 사용할 때는주의하여 행동하십시오.
return ex1.match(S) && ! ex2.match(S)
) 보다 쉬울 수 있습니다 .
나는 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입니다"라고 대답하는 것은 나에게 괜찮아 보입니다. 부분적으로 분해하려면 ... 잊어 버리세요. 내 데이터베이스에 "unpecified adress"를 사용할 필요가 없기 때문에 지정되지 않은 주소 (: :)를 생략했습니다.
시작 :
^([0-9A-Fa-f]{0,4}:){2,7}
<-압축 가능한 부분과 일치, 우리는 이것을 다음과 같이 번역 할 수 있습니다 : 2에서 7 사이의 콜론 사이에 16 진수 숫자가있을 수 있습니다.
뒤에 :
[0-9A-Fa-f]{1,4}$
< ((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.|$)){4}
-16 진수 (선행 0 생략) 또는
<-Ipv4 주소
start() = 0, end() = 3 group(0) = "::1" group(1) = ":" group(2) = "1" group(3) = "null" group(4) = "null" group(5) = "null"
이것은 loopback (:: 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]+)'
ip a | grep -Po '[\w:]+:+[\w:]+'
이 정규식은 REGULAR EXTENDED 모드가 사용 된 regex의 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!) 이 통화는 오래 걸릴 수 있으며 차단 중입니다!
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 주소와 일치하고, 마지막 부분은 영역 색인과 일치) :
(
(
::(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]+)?
그리고 여기에 may 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]+)?
일치하는 간단한 정규식이 있지만 어떤 종류의 유효성 검사도 권장하지 않습니다.
([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}
이것은 루프백 주소 :: 1과는 일치하지 않지만 주소의 모든 압축과 일치합니다. 정규식을 단순하게 유지하기 위해 이것이 합리적인 타협이라고 생각합니다.
iTerm2 스마트 선택 규칙 에서 이것을 성공적으로 사용하여 IPv6 주소를 네 번 클릭합니다.
A-F
아니야 A-Z
! 또한 점으로 구분 된 쿼드 표기법을 제외하고 있습니다.
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
}
}
1200:0000:AB00:1234:0000:2552:7777:1313
들어은 IPv6 주소에 유효한 형식이지만 테스트 메서드가 반환 할 때 유효한 IPv6 주소가 아닙니다. 나는 그것이 241.54.113.65
유효한 IPv4 주소 라고 생각할 것 입니다.
다른 답변에 포함 된 패턴을 살펴보면 그룹을 참조하고 미리보기를 활용하여 개선 할 수있는 좋은 패턴이 많이 있습니다. 다음은 필요한 경우 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에는이 패턴보다 더 나은 솔루션이 될 필터가 내장되어 있습니다.
나는 파이썬을 사용하여 다음을 생성하고 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)
이 답변 중 일부에서 볼 수 있듯이 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
}
Java에서는 라이브러리 클래스를 사용할 수 있습니다 sun.net.util.IPAddressUtil
.
IPAddressUtil.isIPv6LiteralAddress(iPaddress);
모든 IPv6 경우에 작동하는 정규식을 찾는 것은 어렵습니다. 일반적으로 유지 관리가 어렵고 쉽게 읽을 수 없으며 성능 문제를 일으킬 수 있습니다. 따라서 제가 개발 한 대안 솔루션 인 IPv6 용 정규식 (RegEx)을 IPv4와 분리 하여 공유하고 싶습니다.
이제 "이 방법은 IPv6 만 찾습니다. 텍스트 또는 파일에서 IPv6를 어떻게 찾을 수 있습니까?"라고 물을 수 있습니다. 이 문제에 대한 방법도 있습니다.
참고 : .NET에서 IPAddress 클래스를 사용하지 않으려면 my method로 대체 할 수도 있습니다 . 또한 매핑 된 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;
}
}
}
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
이것은 IPv4 및 IPv6에서 작동합니다.
^(([0-9a-f]{0,4}:){1,7}[0-9a-f]{1,4}|([0-9]{1,3}\.){3}[0-9]{1,3})$
::
. 예2404:6800::4003:c02::8a
여기에 약간의 미리보기와 명명 된 그룹을 사용하여 생각해 낸 것입니다. 물론 이것은 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 쉘 도구를 사용할 수 있습니다 . regexp 및 grep을 기반으로합니다.
용법:
$ ifconfig | ipextract6
fe80::1%lo0
::1
fe80::7ed1:c3ff:feec:dee1%en0
대괄호가 포함 된 원본의 로컬 항목 만 일치시킵니다. 나는 그것이 포괄적이지는 않지만 자바 스크립트에서 다른 것들은 주로 작동하지 않는 문제를 추적하기가 어려웠으므로 지금 내가 필요한 것을 얻는 것 같습니다. 추가 대문자 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 하이브리드 없음).
/(?!.*::.*::)(?!.*:::.*)(?!:[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}/
일반 IP (슬래시 없음) 만 원하는 경우 다음과 같습니다.
^(?:[0-9a-f]{1,4}(?:::)?){0,7}::[0-9a-f]+$
호스트 파일 편집기 응용 프로그램의 구문 형광펜에 사용합니다. 매력으로 작동합니다.