有趣的是,上述答案都没有采用原始q的测试例子题目了进去,因为使用它们,所有上述检查将失败(因为#3):
fe80:0000:0000:0000:0202:b3ff:fe1e:8329
fe80:0:0:0:202:b3ff:fe1e:8329
fe80::202:b3ff:fe1e:8329 (!)
IPv6的表示规则说:
一个或多个零值的连续基团可以是使用两个连续的冒号(::),1替换为一个空组,但替换只能在地址中应用一次,因为多次出现会产生模糊表示。 https://en.wikipedia.org/wiki/IPv6_address#Representation
随着Lua的模式不具备Alternation支持,这是不可能的,了解IPv6与单一模式。您可能会看到大卫·M·Syzdek回答关于IPv6的正则表达式的复杂性:https://stackoverflow.com/a/17871737/1895269
不过,更符合标准的做法是保罗Kulchenko的回答如下改进:
function GetIPType(ip)
local R = {ERROR = 0, IPV4 = 1, IPV6 = 2, STRING = 3}
if type(ip) ~= "string" then return R.ERROR end
-- check for format 1.11.111.111 for ipv4
local chunks = { ip:match("^(%d+)%.(%d+)%.(%d+)%.(%d+)$") }
if (#chunks == 4) then
for _,v in pairs(chunks) do
if tonumber(v) > 255 then return R.STRING end
end
return R.IPV4
end
-- check for ipv6 format, should be max 8 'chunks' of numbers/letters
local addr = ip:match("^([a-fA-F0-9:]+)$")
if addr ~= nil and #addr > 1 then
-- address part
local nc, dc = 0, false -- chunk count, double colon
for chunk, colons in addr:gmatch("([^:]*)(:*)") do
if nc > (dc and 7 or 8) then return R.STRING end -- max allowed chunks
if #chunk > 0 and tonumber(chunk, 16) > 65535 then
return R.STRING
end
if #colons > 0 then
-- max consecutive colons allowed: 2
if #colons > 2 then return R.STRING end
-- double colon shall appear only once
if #colons == 2 and dc == true then return R.STRING end
if #colons == 2 and dc == false then dc = true end
end
nc = nc + 1
end
return R.IPV6
end
return R.STRING
end
的脚本来检查:
local IPType = {[0] = "Error", "IPv4", "IPv6", "string"}
local ips = {
"128.1.0.1", -- ipv4
"223.255.254.254", -- ipv4
"999.12345.0.0001", -- invalid ipv4
"1050:0:0:0:5:600:300c:326b", -- ipv6
"[email protected]$300c#326b", -- string
"1050:0:0:0:5:600:300c:326babcdef", -- string
"1050:0000:0000:0000:0005:0600:300c:326b", -- ipv6
"1050:::600:5:1000::", -- contracted ipv6 (invalid)
"fe80::202:b3ff:fe1e:8329", -- shortened ipv6
"fe80::202:b3ff::fe1e:8329", -- shortened ipv6 (invalid)
"fe80:0000:0000:0000:0202:b3ff:fe1e:8329:abcd", -- too many groups
"::1", -- valid IPv6
"::", -- valid IPv6
":", -- string
"129.garbage.9.1", -- string
129.10 -- error
}
for k,v in pairs(ips) do
print(v, IPType[GetIPType(v)])
end
和输出:
128.1.0.1 IPv4
223.255.254.254 IPv4
999.12345.0.0001 string
1050:0:0:0:5:600:300c:326b IPv6
[email protected]$300c#326b string
1050:0:0:0:5:600:300c:326babcdef string
1050:0000:0000:0000:0005:0600:300c:326b IPv6
1050:::600:5:1000:: string
fe80::202:b3ff:fe1e:8329 IPv6
fe80::202:b3ff::fe1e:8329 string
fe80:0000:0000:0000:0202:b3ff:fe1e:8329:abcd string
::1 IPv6
:: IPv6
: string
129.garbage.9.1 string
129.1 Error
我喜欢这种方法,但它说999.12345.0.0001是IPv4,它不能识别签约的IPv6地址: -/ –
给了我一点点,我会尽量让答案更新以处理约定的IPv6格式,并且为IPv4地址格式中的每个IP块添加有效性检查。 –
已更新为包含IPv4地址范围有效性检查 –