【问题标题】:way to set dynamic pattern matcher设置动态模式匹配器的方法
【发布时间】:2016-02-06 00:23:06
【问题描述】:

请查看这个问题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

【问题讨论】:

  • 只是转义魔法字符。
  • 我的错误,我的Solution 2 正在工作,现在如果我们可以使用模式本身进行此操作,那就太好了。我也在更新我的问题:)
  • 请查看this demo
  • @Wiktor:你可以回答那个演示,它正在工作:)

标签: lua lua-patterns


【解决方案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 之一)

【讨论】:

    【解决方案2】:

    这是我的最终解决方案:

    -- 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() )
    

    【讨论】:

      猜你喜欢
      • 2011-04-28
      • 2021-04-07
      • 2021-09-13
      • 1970-01-01
      • 2021-10-23
      • 2021-02-02
      • 1970-01-01
      • 2016-06-08
      相关资源
      最近更新 更多