3

I have this pattern:

^u.meta(\.|$)

EXPECTED BEHAVIOUR

^u.meta(\.|$) will match all the roles like:

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

Where as it should not match something like below:

u.meta_admin
u.meta_admin_system

I have tested this pattern with https://regex101.com/ online regexp tester.

PROBLEM:

I have to implement this pattern with lua script. but getting invalid escape sequence near '\.':

-- lua script

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

And I tried adding double \\ as well as removing '\' escape char in that regexp but got nil in return:

-- lua script

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

> return  string.match("u.meta.admin", '^u.meta(.|$)')
nil
Yu Hao
  • 119,891
  • 44
  • 235
  • 294
przbadu
  • 5,769
  • 5
  • 42
  • 67
  • You need to use `%` instead of ``\``. Use `^u%.meta(%.|$)` – Wiktor Stribiżew Jan 26 '16 at 10:50
  • @WiktorStribiżew: thanks for your quick reply, I am testing that regex – przbadu Jan 26 '16 at 10:53
  • `return string.match("u.meta.admin", '^u%.meta(%.|$)')` still returns `nil` :( – przbadu Jan 26 '16 at 10:53
  • Yes, because `(%.|$)` is not supported. What is your intent here? You want to make sure the `meta` is a whole word (followed with a non-word character?). Try `print(string.match("u.meta.admin", '^u%.meta%f[%A]'))` – Wiktor Stribiżew Jan 26 '16 at 10:56
  • I will give it a try. My intent here is as I have updated `Expected Behaviour` in qustion. `u.meta` should match with anything like `u.meta.*` including `u.meta` – przbadu Jan 26 '16 at 11:00
  • `print(string.match("u.meta.admin", '^u%.meta%f[%A]'))` is working, now I don't want `u.meta_admin` to match this regexp only match `u.meta.*` including `u.meta`, NOTE dot(.) character and underscore (_) – przbadu Jan 26 '16 at 11:03

1 Answers1

4

See Lua regex docs:

The character % works as an escape for those magic characters.

Also, the (...|...) alternation is not supported in Lua. Instead, I guess, you need a word boundary here, like %f[set] frontier pattern:

%f[set], a frontier pattern; such item matches an empty string at any position such that the next character belongs to set and the previous character does not belong to set. The set set is interpreted as previously described. The beginning and the end of the subject are handled as if they were the character \0.

So, you can use

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

To only match at the end or before a .:

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

To match only if the admin is not followed with a letter or an underscore, use a negated character class [^%a_]:

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

See IDEONE demo to check the difference between the two expressions.

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

NOTE To match the end of the string, instead of \0, you can safely use %z (as @moteus noted in his comment) (see this reference):

%z    the character with representation 0

Community
  • 1
  • 1
Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
  • `return string.match("u.meta.admin", '^u%.meta%f[%A]')` is working, now I don't want `u.meta_admin` to match this regexp only match `u.meta.*` including u.meta, NOTE `dot(.)` character and `underscore (_)` – przbadu Jan 26 '16 at 11:05
  • Then try a negated character class approach: `string.match("u.meta_admin", '^u%.meta%f[[^%a_]]')` - match `u.meta` only if not followed by a letter and `_`. – Wiktor Stribiżew Jan 26 '16 at 11:07
  • thanks`print(string.match("u.meta", '^u%.meta%f[\0.]'))` is working now +1 – przbadu Jan 26 '16 at 11:07
  • 1
    Just little note. `\0` is allows only since Lua 5.2. On Lua 5.1 you need use `%z`. This is if you need compat with old Lua version. – moteus Jan 26 '16 at 11:28
  • @moteus: Yes, somehow that eluded my attention. Surely `%z` is a way to go: *`%z` the character with representation `0`* – Wiktor Stribiżew Jan 26 '16 at 11:32