模式'^u.meta(\.|$)'的工作不如预期。

我有这个模式:

^u.meta(\.|$)

预期行为

^u.meta(\.|$) 将匹配所有这样的角色:

u.meta
u.meta.admin
u.meta.admin.system
u.meta.*

但不应该匹配如下所示的内容:

u.meta_admin
u.meta_admin_system

我已经使用 https://regex101.com/ 在线 regexp tester 测试了这个模式。

问题:

我必须使用 lua 脚本实现这个模式,但是却得到 invalid escape sequence near '\.':

-- lua 脚本

> return  string.match("u.meta.admin", '^u.meta(\.|$)')
stdin:1: invalid escape sequence near '\.'

我尝试添加双 \\ 并删除该正则表达式中的 \\ 转义字符,但返回值为 nil:

-- lua 脚本

> return string.match("u.meta.admin", '^u.meta(\\.|$)')
nil

> return  string.match("u.meta.admin", '^u.meta(.|$)')
nil
点赞
用户3832970
用户3832970

Lua 正则文档

% 字符可以用作转义特殊字符。

另外,在 Lua 中不支持 (...|...) 的 alternation。取而代之,我猜您需要使用一个词边界,比如 %f[set] frontier pattern

%f[set]:一个 frontier pattern;这种类型的项目在任何当前字符属于 set 而前一个字符不属于 set 的位置上匹配空字符串。set 的 set 解释方式如前文所述。主题的开头和结尾处理方式如同字 符 \0

因此,您可以使用以下代码:

return string.match("u.meta.admin", '^u%.meta%f[%A]')

只会匹配到 . 的前一个位置或结尾:

return string.match("u.meta", '^u%.meta%f[\0.]')

如果 admin 之后没有跟着一个字母或下划线,则使用否定字符类 [^%a_]

return string.match("u.meta_admin", '^u%.meta%f[[^%a_]]')

请参见这个 IDEONE 演示区别两种表达式的区别

print(string.match("u.meta", '^u%.meta%f[\0.]')) -- u.meta
print(string.match("u.meta.admin", '^u%.meta%f[\0.]')) -- u.meta
print(string.match("u.meta-admin", '^u%.meta%f[\0.]')) -- nil
print(string.match("u.meta", '^u%.meta%f[%A]')) -- u.meta
print(string.match("u.meta.admin", '^u%.meta%f[%A]')) -- u.meta
print(string.match("u.meta-admin", '^u%.meta%f[%A]')) -- u.meta
-- 要排除匹配 `u.admin` 后面跟着的 `_`:
print(string.match("u.meta_admin", '^u%.meta%f[[^%a_]]')) -- nil

注意:要匹配字符串末尾,不要使用 \0,您可以安全地使用 %z(正如@moteus 在评论中注意到的那样)(请参见这个参考):

%z :表示字符 0

2016-01-26 10:59:31