Reputation: 265
Okay so I wanted a regex to parse uncontracted(if that's what it is called) ipv6 adresses
Example ipv6 adress: 1050:::600:5:1000::
What I want returned: 1050:0000:0000:600:5:1000:0000:0000
My try at this:
ip:gsub("%:([^0-9a-zA-Z])", ":0000")
The first problem with this: It replaces the first and second :
So ::
gets replaced with :0000
Replacing it with :0000:
wouldn't work because then it will end with a :
. Also this would note parse the newly added :
resulting in: 1050:0000::600:5:1000:0000:
So what would I need this regex to do?
Replace every :
by :0000
if it isn't followed by a number or letter
Main problem: ::
gets replaced instead of 1 :
Upvotes: 3
Views: 303
Reputation: 3225
There is no single statement pattern to do this but you can use a function to do this for any possible input:
function fill_ip(s)
local ans = {}
for s in (s..':'):gmatch('(%x*):') do
if s == '' then s = '0000' end
ans[ #ans+1 ] = s
end
return table.concat(ans,':')
end
--examples:
print(fill_ip('1050:::600:5:1000::'))
print(fill_ip(':1050:::600:5:1000:'))
print(fill_ip('1050::::600:5:1000:1'))
print(fill_ip(':::::::'))
Upvotes: 1
Reputation: 6251
gsub
and other functions from Lua's string library use Lua Patterns which are much simpler than regex. Using the pattern more than once will handle the cases where the pattern overlaps the replacement text. The pattern only needs to be applied twice since the first time will catch even pairings and the second will catch the odd/new pairings of colons. The trailing and leading colons can be handled separately with their own patterns.
ip = "1050:::600:5:1000::"
ip = ip:gsub("^:", "0000:"):gsub(":$", ":0000")
ip = ip:gsub("::", ":0000:"):gsub("::", ":0000:")
print(ip) -- 1050:0000:0000:600:5:1000:0000:0000
Upvotes: 1