lua-users home
lua-l archive

Re: Patterns

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


It was thus said that the Great Paul Ducklin once stated:
> Why try to convert the matching string into a regexp or Lua pattern at
> all? Sometimes regexp-type code is simply the wrong way to do things, but
> something we do merely from familiarity.
> 
> It sounds as though matching an input string X against the expression
> “/sport/#” in the fashion you describe is equivalent to:
> 
> X == “/sport” or X:sub(1,7) == “/sport/“
> 
> So why not just do it like that, and sidestep regexps, patterns,
> wildcards, state machines, and all that complexity? The code above is
> simpler, faster and self-documenting…
 That actually might be simpler. Proof of concept:
local function match(pattern,target)
 -- --------------------------------------------
 -- I couldn't think of a better way to do this
 -- --------------------------------------------
 if pattern:match("#") and not pattern:match("#$") then
 error "bad pattern"
 end
 local pf,ps,pc = pattern:gmatch "[^/]*" -- capture values from iterator
 local tf,ts,tc = target:gmatch "[^/]*"
 
 while true do
 local pv = pf(ps,pc) -- get next segment in pattern
 local tv = tf(ts,tc) -- get next segment in target
 
 -- ---------------
 -- if we're at the end of the pattern, we should be at the end
 -- of the target
 -- ---------------
 
 if not pv then
 return not tv
 
 -- ----------------------------------------------------------------------
 If the patttern segment is '+', then the target is an automatic match
 -- ----------------------------------------------------------------------
 
 elseif pv == '+' then
 -- nothing to do here
 
 -- -----------------------------------------------------
 -- If the pattern is '#', then everything else matches
 -- -----------------------------------------------------
 
 elseif pv == '#' then
 return true
 
 -- ------------------------------------------------------
 -- compare the two segments, if unequal, result is false
 -- ------------------------------------------------------
 
 else
 if pv ~= tv then
 return false
 end
 end
 end
end
local function test(p,t)
 print(match(p,t),p,t)
end
test("sport/tennis/player1/#","sport/tennis/player1")
test("sport/tennis/player1/#","sport/tennis/player1/ranking")
test("sport/tennis/player1/#","sport/tennis/player1/score/wimbleton")
test("sport/tennis/+","sport/tennis/player1")
test("sport/tennis/+","sport/tennis/player2")
test("sport/tennis/+","sport/tennis/player1/ranking")
test("+/tennis/#","news/tennis")
test("+/tennis/#","news/tennis/mcenroe")
test("+/tennis/#","/tennis/mcenroe")
test("+/tennis/#","sports/tennis/williams")
test("+/tennis/#","sports/tennis/williams/ranking")
test("+/tennis/#","tennis")
test("+/tennis/#","game/fussbol")
test("+/+","/finance")
test("/+","/finance")
test("/sport/#","/sport")
test("/sport/#","/sport/racing")
test("/sport/#","/sport/racing/champion")
test("/sport/#","/sporting")
 -spc

AltStyle によって変換されたページ (->オリジナル) /