local url={parsed={}} --儲存decode出來的key-value--privatelocal function escape(w)pattern="[^%w%d%._%-%* ]"s=string.gsub(w,pattern,function(c)local c=string.format("%%%02X",string.byte(c))return cend)s=string.gsub(s," ","+")return sendlocal function detail_escape(w)local t={}for i=1,#w doc = string.sub(w,i,i)b,e = string.find(c,"[%w%d%._%-'%* ]")if not b thent[#t+1]=string.format("%%%02X",string.byte(c))elset[#t+1]=cendends = table.concat(t)s = string.gsub(s," ","+")return sendlocal function unescape(w)s=string.gsub(w,"+"," ")s,n = string.gsub(s,"%%(%x%x)",function(c)return string.char(tonumber(c,16))end)return send---[=[--public functionfunction url:new()local u={} --對象u.old= nil --上一次decode 字串的值u.de = nil --decode字串後的結果值u.en = nil --encode字串後的結果值u.enold = nil --上一次encode 字串的值u.len = 0 --記錄parsed map的長度--設定metatablesetmetatable(u,{__index=self})return uendfunction url:decode(line)assert(line == nil or type(line) == "string")if self.old == line then return print("url:decode have cache") ,self.de endif not line then return self.de endself.parsed=nilself.len = 0self.parsed={}for k,v in string.gmatch(line,"([^&=]+)=([^&=]+)") doself.len = self.len + 1self.parsed[k] = unescape(v)endif self.len == 0 then return nil endlocal r={}for k,v in pairs(self.parsed) dor[#r+1] = k.."="..vendself.de=table.concat(r,"&")self.old=linereturn self.deendfunction url:encode(t)if(type(t) == "string") thenif t == self.enold thenprint("url:encode have cache")return self.enendlocal r={}for k,v in string.gmatch(t,"([^&=]+)=([^&=]+)") dor[#r+1] = escape(k) .."=".. escape(v)endself.en = table.concat(r,"&")self.enold = treturn self.enelseif type(t) ~= "table" then return nilelselocal r = {}for k , v in pairs(t) dor[#r+1] = escape(k) .."=".. escape(v)endself.en = table.concat(r,"&")return self.enendendfunction url:parse(line)assert(line == nil or type(line) == "string")if not line thenif self.len == 0 then return nilelse return self.parsed endendif url:decode(line) == nil then return nil endreturn self.parsedendfunction url:get(k)if self.len > 0 thenreturn self.parsed[k]elsereturn nilendend--測試私人函數test="泰囧<>2a+b=c.*!^()"test2="tn=baiduhome_pg&ie=utf-8&bs=lua%26%3D+%E5%8C%B9%E9%85%8D%E6%B1%89%E5%AD%97&f=8&rsv_bp=1&rsv_spt=1&wd=%E6%B3%B0%E5%9B%A7%3C%3E2a%2Bb+%3D+c.*%21%5E%28%29&rsv_n=2&rsv_sug3=1&rsv_sug1=1&rsv_sug4=168&inputT=897"---[[io.write("test private funcitons\n")io.write("test:",test,"\n")io.write("結果:",escape(test),"\n")io.write("結果:",detail_escape(test),"\n")dec=detail_escape(test)io.write("結果:",unescape(dec),"\n")--]]--測試公有函數show = function(m)if not m then io.write("empty")elseif type(m) == "string" thenio.write(m)elseif type(m) == "table" thenfor k,v in pairs(m) doio.write(string.format("k=%-10s v=%s\n",k,v))endelseio.write("unkown")endio.write("\n")endio.write("test public funcitons\n")local u = url:new()io.write("encode(test):");show(u:encode(test))io.write("encode(test2):");show(u:encode(test2))io.write("decode(encode(test)):");show(u:decode(u:encode(test)))io.write("decode(test2):");show(u:decode(test2))io.write("decode(test2):");show(u:decode(test2))io.write("encode(test2):");show(u:encode(test2))io.write("parse(encode(test2)):");show(u:parse(u:encode(test2)))io.write("encode(map):"); show(u:encode({a="x + 3*10 << 1&2",b="q=queryWord!"}))io.write("decode(encode(map):");show(u:decode(u:encode({a="x + 3*10 << 1&2",b="q=queryWord!"})))print("decode test2:",test2);d=u:decode(test2)print("decode test2 ret:",d);print("encode d:",d)e=u:encode(d)print("encode d ret:",e)p=u:parse(e)show(p)io.write("parse:");show(u:parse(u:encode(u:decode(test2))))io.write("get f:");show(u:get("f"))io.write("get a :");show(u:get("a"))io.write("get tn :");show(u:get("tn"))io.write("get bw :");show(u:get("bw"))io.write("get cda:");show(u:get("cda"))return url--]=]
就利用string的正則匹配操作url進行編碼和轉換,空格轉成'+',而不是%20,這主要和瀏覽器轉一樣。
做成了一個模組,可以直接用,下面看代碼