我想有一个函数,我可以传递一个空白修剪字符串,它将返回
0表示错误(不是字符串)1表示ipv4 2表示ipv6 3表示字符串不是ip.
Ipv6有这些规则:
Ipv6由8组由冒号(:)分隔的16位十六进制值表示
.十六进制数字不区分大小写
缩写规则:
1:在16位值中省略前导零
2:用一组或多组连续零替换双结肠
wiki示例显示3种方式都是相同的ipv6:
fe80:0000:0000:0000:0202:b3ff:fe1e:8329
fe80:0:0:0:202:b3ff:fe1e:8329
fe80::202:b3ff:fe1e:8329
Run Code Online (Sandbox Code Playgroud)
我有理由相信ipv4你只需要检查三个.然后检查字符串是否所有
数字和.的计数为数字,最后一个字符串的检查
将在if语句的末尾,所以如果它不是ipv4/6及其字符串则
返回3
Mike的解决方案很好,但可以通过多种方式改进.在目前的形式,它没有得到ipv6地址检查,但它很容易修复.ipv6检查在诸如"1050!0!0+0-5@600$300c#326b"和"1050:0:0:0:5:600:300c:326babcdef"(将其识别为有效地址)和"1050:::600:5:1000::"(将其识别为字符串)之类的事情上失败.
以下是改进版本(假设IPv4为十进制数,IPv6假定为十六进制数):
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 8 'chunks' of numbers/letters
-- without leading/trailing chars
-- or fewer than 8 chunks, but with only one `::` group
local chunks = {ip:match("^"..(("([a-fA-F0-9]*):"):rep(8):gsub(":$","$")))}
if #chunks == 8
or #chunks < 8 and ip:match('::') and not ip:gsub("::","",1):match('::') then
for _,v in pairs(chunks) do
if #v > 0 and tonumber(v, 16) > 65535 then return R.STRING end
end
return R.IPV6
end
return R.STRING
end
Run Code Online (Sandbox Code Playgroud)
要检查的脚本:
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
"1050!0!0+0-5@600$300c#326b", -- string
"1050:0:0:0:5:600:300c:326babcdef", -- string
"1050:0000:0000:0000:0005:0600:300c:326b", -- ipv6
"fe80:0000:0000:0000:0202:b3ff:fe1e:8329", -- ipv6
"fe80:0:0:0:202:b3ff:fe1e:8329", -- ipv6
"fe80::202:b3ff:fe1e:8329", -- ipv6
"1050:::600:5:1000::", -- contracted ipv6
"::", -- ipv6
"::1", -- ipv6
"::1::", -- string
"129.garbage.9.1", -- string
"xxx127.0.0.0", -- error
"xxx1050:0000:0000:0000:0005:0600:300c:326b", -- string
129.10 -- error
}
for k,v in pairs(ips) do
print(v, IPType[GetIPType(v)])
end
Run Code Online (Sandbox Code Playgroud)
并输出:
128.1.0.1 IPv4
223.255.254.254 IPv4
999.12345.0.0001 string
1050:0:0:0:5:600:300c:326b IPv6
1050!0!0+0-5@600$300c#326b string
1050:0:0:0:5:600:300c:326babcdef string
1050:0000:0000:0000:0005:0600:300c:326b IPv6
fe80:0000:0000:0000:0202:b3ff:fe1e:8329 IPv6
fe80:0:0:0:202:b3ff:fe1e:8329 IPv6
fe80::202:b3ff:fe1e:8329 IPv6
1050:::600:5:1000:: IPv6
:: IPv6
::1 IPv6
::1:: string
129.garbage.9.1 string
xxx127.0.0.0 string
xxx1050:0000:0000:0000:0005:0600:300c:326b string
129.1 Error
Run Code Online (Sandbox Code Playgroud)
更新于9/6/2018,在地址之前/之后添加垃圾处理并检查签约的ipv6,这允许少于8个组,其中一个空组包含两个连续冒号.
这似乎是一个需要解决的非常基本的问题。我认为这个功能可以满足您的需要......
function GetIPType(ip)
-- must pass in a string value
if ip == nil or type(ip) ~= "string" then
return 0
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) < 0 or tonumber(v) > 255) then
return 0
end
end
return 1
else
return 0
end
-- check for ipv6 format, should be 8 'chunks' of numbers/letters
local _, chunks = ip:gsub("[%a%d]+%:?", "")
if chunks == 8 then
return 2
end
-- if we get here, assume we've been given a random string
return 3
end
Run Code Online (Sandbox Code Playgroud)
用这段代码测试了它:
local IPType = {
[0] = "Error",
[1] = "IPv4",
[2] = "IPv6",
[3] = "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
"1050:0000:0000:0000:0005:0600:300c:326b", -- ipv6
"1050:::600:5:1000::", -- contracted ipv6
"129.garbage.9.1", -- string
129.10 -- error
}
for k,v in pairs(ips) do
print(v, IPType[GetIPType(v)])
end
Run Code Online (Sandbox Code Playgroud)
生成此输出:
128.1.0.1 IPv4
223.255.254.254 IPv4
1050:0:0:0:5:600:300c:326b IPv6
1050:0000:0000:0000:0005:0600:300c:326b IPv6
129.garbage.9.1 string
129.1 Error
Run Code Online (Sandbox Code Playgroud)
将来,如果您实际发布您尝试编写的代码来解决您的特定问题,您将获得更多有用的反馈,并让我们知道您在哪里需要帮助。正如常见问题解答中所述,SO 不是个人代码编写服务。不过,我会给你一个无罪推论,因为你看起来很新,而且这可能会让其他人受益。上面的代码是基本的,所以如果它没有捕获我不知道的边缘测试用例,请随时更新它。