Шаблон ^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 script

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

И я попытался добавить двойной \\, а также удалить escape-символ '\' в этом регулярном выражении, но в ответ получил ноль:

-- lua script

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

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

person przbadu    schedule 26.01.2016    source источник
comment
Вам нужно использовать % вместо \. Используйте ^u%.meta(%.|$)   -  person Wiktor Stribiżew    schedule 26.01.2016
comment
@WiktorStribiżew: спасибо за быстрый ответ, я тестирую это регулярное выражение   -  person przbadu    schedule 26.01.2016
comment
return string.match("u.meta.admin", '^u%.meta(%.|$)') все равно возвращает nil :(   -  person przbadu    schedule 26.01.2016
comment
Да, потому что (%.|$) не поддерживается. Каковы ваши намерения здесь? Вы хотите убедиться, что meta является целым словом (за которым следует символ, не являющийся словом?). Попробуйте print(string.match("u.meta.admin", '^u%.meta%f[%A]'))   -  person Wiktor Stribiżew    schedule 26.01.2016
comment
Я дам ему попробовать. Мое намерение здесь, поскольку я обновил Expected Behaviour в вопросе. u.meta должно совпадать с чем-то вроде u.meta.*, включая u.meta   -  person przbadu    schedule 26.01.2016
comment
print(string.match("u.meta.admin", '^u%.meta%f[%A]')) работает, теперь я не хочу, чтобы u.meta_admin соответствовало этому регулярному выражению, только соответствует u.meta.*, включая u.meta, ПРИМЕЧАНИЕ: символ точки (.) и символ подчеркивания (_)   -  person przbadu    schedule 26.01.2016


Ответы (1)


См. документацию по регулярным выражениям Lua:

Символ % работает как побег для этих магических символов.

Кроме того, чередование (...|...) не поддерживается в Lua. Вместо этого, я думаю, вам нужна граница слова, например %f[set] шаблон границы :

%f[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
-- To exclude a match if `u.admin` is followed with `_`:
print(string.match("u.meta_admin", '^u%.meta%f[[^%a_]]')) -- nil

ПРИМЕЧАНИЕ Чтобы соответствовать концу строки, вместо \0 можно безопасно использовать %z (как @moteus отметил в своем комментарии) (см. эта ссылка):

%z персонаж с представлением 0

person Wiktor Stribiżew    schedule 26.01.2016
comment
return string.match("u.meta.admin", '^u%.meta%f[%A]') работает, теперь я не хочу, чтобы u.meta_admin соответствовало этому регулярному выражению, соответствовало только u.meta.*, включая u.meta, ПРИМЕЧАНИЕ dot(.) символ и underscore (_) - person przbadu; 26.01.2016
comment
Затем попробуйте подход с инвертированным классом символов: string.match("u.meta_admin", '^u%.meta%f[[^%a_]]') — соответствует u.meta, только если за ним не следует буква и _. - person Wiktor Stribiżew; 26.01.2016
comment
спасибоprint(string.match("u.meta", '^u%.meta%f[\0.]')) теперь работает +1 - person przbadu; 26.01.2016
comment
Просто маленькая заметка. \0 разрешено только начиная с Lua 5.2. В Lua 5.1 вам нужно использовать %z. Это если вам нужна совместимость со старой версией Lua. - person moteus; 26.01.2016
comment
@moteus: Да, как-то это ускользнуло от моего внимания. Конечно, %z — это то, что нужно: %z персонаж с представлением 0 - person Wiktor Stribiżew; 26.01.2016