2016-01-27 3 views
3

Пожалуйста, изучите этот вопрос Pattern ^u.meta(\.|$) not working as expected, который имеет ожидаемое поведение, которое мне нужно.способ установки динамического шаблона соответствия

МЕНЯЕТ

В шаблоне ^u.meta(\.|$) или в Lua '^u%.meta%f[\0.]' или '^u%.meta%f[%z.]', изменение мне нужно u.meta может быть все, что определяется пользователем с переменной. И шаблон должен быть общим/динамическим, чтобы соответствовать тому, что установлено в переменной.

Например:

-- should return 'u.meta', and pattern should match 
local pattern = 'u.meta' 
print(string.match("u.meta.admin", '^u%.meta%f[\0.]')) -- u.meta 

-- should return 'nil', and pattern should fail 
local pattern = 'u.meta' 
print(string.match("u.domain.admin", '^u%.meta%f[\0.]')) -- nil 

-- should return 'anything.anything', and pattern should match 
local pattern = 'anything.anything' 
print(string.match("anything.anything.something", '^anything%.anything%f[\0.]') -- anything.anything 

-- should return nil, and pattern should fail 
local pattern = 'anything.anything' 
print(string.match("fake.fake.something", '^anything%.anything%f[\0.]') -- nil 

РЕШЕНИЕ 1

так, что я думал, что-то вроде interpolation в Lua модели, если это возможно.

"^#{pattern}%f[\0.]" 

РАБОЧИЙ РАСТВОР 2

Я сделал работу с помощью метода. Но все же я должен называть этот шаблон вручную. Если мы сможем это исправить с самим шаблона, было бы здорово

Пример:

function pattern_matcher(v, pattern) return string.match(v, pattern) end 

print(pattern_matcher("fake.fake.something", '^u%.meta%f[%z.]')) -- nil 
print(pattern_matcher("u.meta.something", '^u%.meta%f[%z.]')) -- u.meta 
print(pattern_matcher("u.meta_something", '^u%.meta%f[%z.]')) -- nil 
print(pattern_matcher("u.meta-something", '^u%.meta%f[%z.]')) -- nil 
+0

Просто избегайте волшебных символов. – moteus

+0

My Bad, мое решение «2» работает, теперь, если мы сможем заставить это работать с самим шаблоном, тогда было бы здорово. Я также обновляю свой вопрос :) – przbadu

+1

Пожалуйста, проверьте [это демо] (https://ideone.com/CEwFEY). –

ответ

1

Если вам необходимо поддерживать ввод данных пользователя в качестве буквальных частей шаблона регулярного выражения, вам нужно ввести ускользающую функцию так что все магические персонажи сбегали с %. Затем просто конкатенация с пользовательскими границами (начало строки и %f[%z.] для конца строки или точки).

function escape (s) 
     return string.gsub(s, '[.*+?^$()[%%-]', "%%%0") 
end 
function pattern_matcher(v, pattern) return string.match(v, pattern) end 

word = "u.meta" 
print(pattern_matcher("u.meta.something", '^' .. escape(word) .. '%f[%z.]')) -- u.meta 

См this demo

В функции escape, первые два %% в схеме замещения обозначают один % и %0 обратные_связи весь матч (один из magic characters)

1

Вот мой последний раствор:

-- USAGE: 
-- 
-- local t  = {} 
-- t['roles'] = 'u.meta.admin' 
-- match_roles(t, 'u.meta') -- u.meta 
-- match_roles(t, 'u.fake') -- nil 
-- 
-- SOLUTION 1 
-------------- 
-- 
-- function u_meta(v) return string.match(v, '^u%.meta%f[%z.]') end 
-- function u_domain(v) return string.match(v, '^u%.domain%f[%z.]') end 
-- 
-- function match_roles(table, pattern) 
-- for _, value in pairs(table) do 
--  if pattern == "u.meta" then 
--  if pattern == u_meta(value) then return true end 
--  elseif pattern == "u.domain" then 
--  if pattern == u_domain(value) then return true end 
--  end 
--  return false 
-- end 
-- end 

-- SOLUTION 2 
--------------- 
-- 
-- function pattern_matcher(v, p) return string.match(v, p) end 
-- function match_roles(table, role, pattern) 
-- for _, value in pairs(table) do 
--  if role == pattern_matcher(value, pattern) then return true end 
--  return false 
-- end 
-- end 

-- SOLUTIN - 3 (GENERIC SOLUTION) - Thanks Wiktor for pattern 
--------------------------------- 

function escape (s) return string.gsub(s, '[.*+?^$()[%%-]', "%%%0") end 
function pattern_matcher(v, pattern) return string.match(v, pattern) end 
function match_roles(table, pattern) 
    for _, value in pairs(table) do 
    if pattern == pattern_matcher(value, '^' .. escape(pattern) .. '%f[%z.]') then return true end 
    return false 
    end 
end 


-- UNIT TEST 
-- --------- 
-- 
-- Below section covers unit test in lua. 
-- we are using `luaunit` unit-testing framework that works for lua. 
-- NOTE: LuaUnit works with Lua 5.1, 5.2, 5.3 and luajit (v1 and v2.1), 
-- http://luaunit.readthedocs.org/en/latest/ 
-- 
package.path = './lib/?.lua;' .. package.path 
luaunit = require('luaunit') 
local t = {} 

function test_meta_user_should_be_true() 
    t["roles"] = 'u.meta.admin.system' 
    luaunit.assertEquals(match_roles(t, 'u.meta'), true) 
end 

function test_meta_admin_should_be_true() 
    t["roles"] = 'u.meta.admin' 
    luaunit.assertEquals(match_roles(t, 'u.meta'), true) 
end 

function test_system_admin_should_be_true() 
    t["roles"] = 'u.meta.admin.system' 
    luaunit.assertEquals(match_roles(t, 'u.meta'), true) 
end 

function test_invalid_meta_admin_should_be_false() 
    t["roles"] = 'u.meta_admin' 
    luaunit.assertEquals(match_roles(t, 'u.meta'), false) 
end 

function test_invalid_meta_admin_system_should_be_false() 
    t["roles"] = 'u.meta_admin_system' 
    luaunit.assertEquals(match_roles(t, 'u.meta'), false) 
end 

function test_invalid_role_should_be_false() 
    t["roles"] = 'u.meta-admin' 
    luaunit.assertEquals(match_roles(t, 'u.meta'), false) 
end 

function test_domain_should_not_allow_in_meta() 
    t['roles'] = 'u.domain' 
    luaunit.assertEquals(match_roles(t, 'u.meta'), false) 
end 

function test_domain_user_should_be_true() 
    t["roles"] = 'u.domain' 
    luaunit.assertEquals(match_roles(t, 'u.domain'), true) 
end 

function test_domain_admin_should_be_true() 
    t["roles"] = 'u.domain.admin' 
    luaunit.assertEquals(match_roles(t, 'u.domain'), true) 
end 

function test_fake_domain_admin_should_be_falsy() 
    t["roles"] = 'u.domain_admin' 
    luaunit.assertEquals(match_roles(t, 'u.domain'), false) 
end 

function test_fake_role_should_be_falsy() 
    t["roles"] = 'u.domain-admin' 
    luaunit.assertEquals(match_roles(t, 'u.domain'), false) 
end 

function test_user_should_either_domain_or_meta() 
    t["roles"] = 'u' 
    luaunit.assertEquals(match_roles(t, 'u.domain'), false) 
end 

function test_meta_user_in_domain_should_be_false() 
    t["roles"] = 'u.meta' 
    luaunit.assertEquals(match_roles(t, 'u.domain'), false) 
end 

function test_meta_admin_in_domain_should_be_false() 
    t["roles"] = 'u.meta.admin' 
    luaunit.assertEquals(match_roles(t, 'u.domain'), false) 
end 

function test_system_admin_in_domain_should_be_false() 
    t["roles"] = 'u.meta.admin.system' 
    luaunit.assertEquals(match_roles(t, 'u.domain'), false) 
end 

function test_fake_meta_admin_in_domain_should_be_true() 
    t["roles"] = 'u.meta_admin' 
    luaunit.assertEquals(match_roles(t, 'u.domain'), false) 
end 

function test_fake_system_admin_in_domain_should_be_true() 
    t["roles"] = 'u.meta_admin_system' 
    luaunit.assertEquals(match_roles(t, 'u.domain'), false) 
end 

function test_fake_meta_role_in_domain_should_be_true() 
    t["roles"] = 'u.meta-admin' 
    luaunit.assertEquals(match_roles(t, 'u.domain'), false) 
end 

function test_anything_should_match_correct_pattern() 
    t['roles'] = 'a.b.c.z' 
    luaunit.assertEquals(match_roles(t, 'a.b'), true) 
end 

function test_anything_should_fail_incorrect_pattern() 
    t['roles'] = 'a.b_c' 
    luaunit.assertEquals(match_roles(t, 'a.b'), false) 
end 

-- Exit after testcases finished 
os.exit(luaunit.LuaUnit.run()) 
Смежные вопросы