在国内IPv4环境下可通过ipv6proxy.cn来对IPv6 only 的网站进行内容测试。下面是IPv6常用的正则表达式世界级解决方案:
一、来自Stephen Ryan的IPv6万能正则表达式:
https://community.fortra.com/forums/intermapper/miscellaneous-topics/5acc4fcf-fa83-e511-80cf-0050568460e4?_ga=2.113564423.1432958022.1523882681-2146416484.1523557976
/^\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]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){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]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){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]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){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]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){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]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/
这个表达式可以判断如下类型的ipv6地址:
fe80:0000:0000:0000:0204:61ff:fe9d:f156 // full form of IPv6
fe80:0:0:0:204:61ff:fe9d:f156 // drop leading zeroes
fe80::204:61ff:fe9d:f156 // collapse multiple zeroes to :: in the IPv6 address
fe80:0000:0000:0000:0204:61ff:254.157.241.86 // IPv4 dotted quad at the end
fe80:0:0:0:0204:61ff:254.157.241.86 // drop leading zeroes, IPv4 dotted quad at the end
fe80::204:61ff:254.157.241.86 // dotted quad at the end, multiple zeroes collapsed
::1 // localhost
fe80:: // link-local prefix
2001:: // global unicast prefix
二、Aeron 为 Perl 和 Java 贡献了更短的 RE:(注意,这些 RE 并不总是忽略 IPv6 地址之前或之后的空格)
Perl:
/^(((?=(?>.*?::)(?!.*::)))(::)?(([0-9A-F]{1,4})::?) {0,5}|((?5):){6})(((?5)(::?|$)){0,2}|((25[0-5]|(2 [0-4]|1[0-9]|[1-9])?[0-9])(\.|$)){4}|(?5):(?5))(?< ![^:]:|\.)\z/i
Java(作为字符串,需要设置 i-flag):
"^(((?=(?>.*?::)(?!.*::)))(::)?([0-9A-F]{1,4}::?){0 ,5}|([0-9A-F]{1,4}:){6})(([0-9A-F]{1,4}(::?|$)){0, 2}|((25[0-5]|(2[0-4]|1\d|[1-9])?\d)(\.|$)){4}|[0-9A- F]{1,4}:[0-9A-F]{1,4})(?<![^:]:|\.)\z"
三、CPAN 模块 Regexp::IPv6
请查看官网:https://metacpan.org/release/SALVA/Regexp-IPv6-0.03/view/lib/Regexp/IPv6.pm
use Regexp::IPv6 qw($IPv6_re);
$address =~ /^$IPv6_re$/ and print "IPv6 address\n";
四、ruby的写法:
请查看官网:https://gist.github.com/cpetschnig/294476
# Regular Expression Validation for IPv6 addresses in Ruby
#
# Inspired by (if not to say copied from): http://forums.dartware.com/viewtopic.php?t=452
# Thanks, Dartware!
IPV6_REGEX = /^\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]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){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]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){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]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){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]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){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]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/
class Validator
def initialize
@valid_false = []
@invalid_false = []
end
def ipv6(string)
result = string =~ IPV6_REGEX
print result ? '.' : 'F'
@valid_false << string unless result
end
def not_ipv6(string)
result = (string =~ IPV6_REGEX).nil?
print result ? '.' : 'F'
@invalid_false << string unless result
end
def to_s
output = "\n"
output += "\nEverything's fine!" if @valid_false.empty? && @invalid_false.empty?
unless @valid_false.empty?
output += "\nThe following addresses are valid, but fail the test:\n"
@valid_false.each{|obj| output += "#{obj}\n"}
end
unless @invalid_false.empty?
output += "\nThe following addresses are not valid, but pass the test:\n"
@invalid_false.each{|obj| output += "#{obj}\n"}
end
output
end
end
assert = Validator.new
assert.not_ipv6("")
assert.ipv6("2001:0000:1234:0000:0000:C1C0:ABCD:0876")
assert.ipv6("3ffe:0b00:0000:0000:0001:0000:0000:000a")
assert.ipv6("FF02:0000:0000:0000:0000:0000:0000:0001")
assert.ipv6("0000:0000:0000:0000:0000:0000:0000:0001")
assert.ipv6("0000:0000:0000:0000:0000:0000:0000:0000")
assert.ipv6("::ffff:192.168.1.26")
assert.not_ipv6("02001:0000:1234:0000:0000:C1C0:ABCD:0876") # extra 0 not allowed!
assert.not_ipv6("2001:0000:1234:0000:00001:C1C0:ABCD:0876") # extra 0 not allowed!
assert.ipv6(" 2001:0000:1234:0000:0000:C1C0:ABCD:0876")
assert.ipv6(" 2001:0000:1234:0000:0000:C1C0:ABCD:0876 ")
assert.not_ipv6(" 2001:0000:1234:0000:0000:C1C0:ABCD:0876 0")
assert.not_ipv6("2001:0000:1234: 0000:0000:C1C0:ABCD:0876")
assert.not_ipv6("3ffe:0b00:0000:0001:0000:0000:000a")
assert.not_ipv6("FF02:0000:0000:0000:0000:0000:0000:0000:0001")
assert.not_ipv6("3ffe:b00::1::a")
assert.not_ipv6("::1111:2222:3333:4444:5555:6666::")
assert.ipv6("2::10")
assert.ipv6("ff02::1")
assert.ipv6("fe80::")
assert.ipv6("2002::")
assert.ipv6("2001:db8::")
assert.ipv6("2001:0db8:1234::")
assert.ipv6("::ffff:0:0")
assert.ipv6("::1")
assert.ipv6("::ffff:192.168.1.1")
assert.ipv6("1:2:3:4:5:6:7:8")
assert.ipv6("1:2:3:4:5:6::8")
assert.ipv6("1:2:3:4:5::8")
assert.ipv6("1:2:3:4::8")
assert.ipv6("1:2:3::8")
assert.ipv6("1:2::8")
assert.ipv6("1::8")
assert.ipv6("1::2:3:4:5:6:7")
assert.ipv6("1::2:3:4:5:6")
assert.ipv6("1::2:3:4:5")
assert.ipv6("1::2:3:4")
assert.ipv6("1::2:3")
assert.ipv6("1::8")
assert.ipv6("::2:3:4:5:6:7:8")
assert.ipv6("::2:3:4:5:6:7")
assert.ipv6("::2:3:4:5:6")
assert.ipv6("::2:3:4:5")
assert.ipv6("::2:3:4")
assert.ipv6("::2:3")
assert.ipv6("::8")
assert.ipv6("1:2:3:4:5:6::")
assert.ipv6("1:2:3:4:5::")
assert.ipv6("1:2:3:4::")
assert.ipv6("1:2:3::")
assert.ipv6("1:2::")
assert.ipv6("1::")
assert.ipv6("1:2:3:4:5::7:8")
assert.not_ipv6("1:2:3::4:5::7:8")
assert.not_ipv6("12345::6:7:8")
assert.ipv6("1:2:3:4::7:8")
assert.ipv6("1:2:3::7:8")
assert.ipv6("1:2::7:8")
assert.ipv6("1::7:8")
assert.ipv6("1:2:3:4:5:6:1.2.3.4")
assert.ipv6("1:2:3:4:5::1.2.3.4")
assert.ipv6("1:2:3:4::1.2.3.4")
assert.ipv6("1:2:3::1.2.3.4")
assert.ipv6("1:2::1.2.3.4")
assert.ipv6("1::1.2.3.4")
assert.ipv6("1:2:3:4::5:1.2.3.4")
assert.ipv6("1:2:3::5:1.2.3.4")
assert.ipv6("1:2::5:1.2.3.4")
assert.ipv6("1::5:1.2.3.4")
assert.ipv6("1::5:11.22.33.44")
assert.not_ipv6("1::5:400.2.3.4")
assert.not_ipv6("1::5:260.2.3.4")
assert.not_ipv6("1::5:256.2.3.4")
assert.not_ipv6("1::5:1.256.3.4")
assert.not_ipv6("1::5:1.2.256.4")
assert.not_ipv6("1::5:1.2.3.256")
assert.not_ipv6("1::5:300.2.3.4")
assert.not_ipv6("1::5:1.300.3.4")
assert.not_ipv6("1::5:1.2.300.4")
assert.not_ipv6("1::5:1.2.3.300")
assert.not_ipv6("1::5:900.2.3.4")
assert.not_ipv6("1::5:1.900.3.4")
assert.not_ipv6("1::5:1.2.900.4")
assert.not_ipv6("1::5:1.2.3.900")
assert.not_ipv6("1::5:300.300.300.300")
assert.not_ipv6("1::5:3000.30.30.30")
assert.not_ipv6("1::400.2.3.4")
assert.not_ipv6("1::260.2.3.4")
assert.not_ipv6("1::256.2.3.4")
assert.not_ipv6("1::1.256.3.4")
assert.not_ipv6("1::1.2.256.4")
assert.not_ipv6("1::1.2.3.256")
assert.not_ipv6("1::300.2.3.4")
assert.not_ipv6("1::1.300.3.4")
assert.not_ipv6("1::1.2.300.4")
assert.not_ipv6("1::1.2.3.300")
assert.not_ipv6("1::900.2.3.4")
assert.not_ipv6("1::1.900.3.4")
assert.not_ipv6("1::1.2.900.4")
assert.not_ipv6("1::1.2.3.900")
assert.not_ipv6("1::300.300.300.300")
assert.not_ipv6("1::3000.30.30.30")
assert.not_ipv6("::400.2.3.4")
assert.not_ipv6("::260.2.3.4")
assert.not_ipv6("::256.2.3.4")
assert.not_ipv6("::1.256.3.4")
assert.not_ipv6("::1.2.256.4")
assert.not_ipv6("::1.2.3.256")
assert.not_ipv6("::300.2.3.4")
assert.not_ipv6("::1.300.3.4")
assert.not_ipv6("::1.2.300.4")
assert.not_ipv6("::1.2.3.300")
assert.not_ipv6("::900.2.3.4")
assert.not_ipv6("::1.900.3.4")
assert.not_ipv6("::1.2.900.4")
assert.not_ipv6("::1.2.3.900")
assert.not_ipv6("::300.300.300.300")
assert.not_ipv6("::3000.30.30.30")
assert.ipv6("fe80::217:f2ff:254.7.237.98")
assert.ipv6("fe80::217:f2ff:fe07:ed62")
assert.ipv6("2001:DB8:0:0:8:800:200C:417A") # unicast, full
assert.ipv6("FF01:0:0:0:0:0:0:101") # multicast, full
assert.ipv6("0:0:0:0:0:0:0:1") # loopback, full
assert.ipv6("0:0:0:0:0:0:0:0") # unspecified, full
assert.ipv6("2001:DB8::8:800:200C:417A") # unicast, compressed
assert.ipv6("FF01::101") # multicast, compressed
assert.ipv6("::1") # loopback, compressed, non-routable
assert.ipv6("::") # unspecified, compressed, non-routable
assert.ipv6("0:0:0:0:0:0:13.1.68.3") # IPv4-compatible IPv6 address, full, deprecated
assert.ipv6("0:0:0:0:0:FFFF:129.144.52.38") # IPv4-mapped IPv6 address, full
assert.ipv6("::13.1.68.3") # IPv4-compatible IPv6 address, compressed, deprecated
assert.ipv6("::FFFF:129.144.52.38") # IPv4-mapped IPv6 address, compressed
# assert.ipv6("2001:0DB8:0000:CD30:0000:0000:0000:0000/60") # full, with prefix
# assert.ipv6("2001:0DB8::CD30:0:0:0:0/60") # compressed, with prefix
# assert.ipv6("2001:0DB8:0:CD30::/60") # compressed, with prefix #2
# assert.ipv6("::/128") # compressed, unspecified address type, non-routable
# assert.ipv6("::1/128") # compressed, loopback address type, non-routable
# assert.ipv6("FF00::/8") # compressed, multicast address type
# assert.ipv6("FE80::/10") # compressed, link-local unicast, non-routable
# assert.ipv6("FEC0::/10") # compressed, site-local unicast, deprecated
# assert.not_ipv6("124.15.6.89/60") # standard IPv4, prefix not allowed
assert.not_ipv6("2001:DB8:0:0:8:800:200C:417A:221") # unicast, full
assert.not_ipv6("FF01::101::2") # multicast, compressed
assert.not_ipv6("") # nothing
assert.ipv6("fe80:0000:0000:0000:0204:61ff:fe9d:f156")
assert.ipv6("fe80:0:0:0:204:61ff:fe9d:f156")
assert.ipv6("fe80::204:61ff:fe9d:f156")
# Not sure about this one; apparently some systems treat the leading "0" in ".086" as the start of an octal number
assert.not_ipv6("fe80:0000:0000:0000:0204:61ff:254.157.241.086")
assert.ipv6("fe80:0:0:0:204:61ff:254.157.241.86")
assert.ipv6("fe80::204:61ff:254.157.241.86")
assert.ipv6("::1")
assert.ipv6("fe80::")
assert.ipv6("fe80::1")
assert.not_ipv6(":")
# Aeron supplied these test cases.
assert.not_ipv6("1111:2222:3333:4444::5555:")
assert.not_ipv6("1111:2222:3333::5555:")
assert.not_ipv6("1111:2222::5555:")
assert.not_ipv6("1111::5555:")
assert.not_ipv6("::5555:")
assert.not_ipv6(":::")
assert.not_ipv6("1111:")
assert.not_ipv6(":")
assert.not_ipv6(":1111:2222:3333:4444::5555")
assert.not_ipv6(":1111:2222:3333::5555")
assert.not_ipv6(":1111:2222::5555")
assert.not_ipv6(":1111::5555")
assert.not_ipv6(":::5555")
assert.not_ipv6(":::")
assert.not_ipv6("1.2.3.4:1111:2222:3333:4444::5555")
assert.not_ipv6("1.2.3.4:1111:2222:3333::5555")
assert.not_ipv6("1.2.3.4:1111:2222::5555")
assert.not_ipv6("1.2.3.4:1111::5555")
assert.not_ipv6("1.2.3.4::5555")
assert.not_ipv6("1.2.3.4::")
assert.not_ipv6("2001:1:1:1:1:1:255Z255X255Y255")
assert.not_ipv6("::ffff:192x168.1.26")
#assert.ipv6("foo")
#assert.not_ipv6("::1")
puts assert
五、IPv6 CIDR 正则(以 CIDR
表示法匹配IP地址的正则表达式)
$ npm i -S cidr-regex
const cidrRegex = require('cidr-regex');
// Contains a CIDR IP address?
cidrRegex().test('foo 192.168.0.1/24');
=> true
// Is a CIDR IP address?
cidrRegex({exact: true}).test('foo 192.168.0.1/24');
=> false
cidrRegex.v6({exact: true}).test('1:2:3:4:5:6:7:8/64');
=> true
// Extract CIDRs from string
'foo 192.168.0.1/24 bar 1:2:3:4:5:6:7:8/64 baz'.match(cidrRegex());
=> ['192.168.0.1/24', '1:2:3:4:5:6:7:8/64']
六、正则可视化:https://jex.im/regulex