How to reduce this regex to fit in Lua?

Viewed 79

I'm trying to do a regex that captures the longest string before a possibly ending letter "c", in Lua.

For example,

  • Given abc, match ab
  • Given acc, match ac
  • Given abcd, match abcd
  • Given abd, match abd

The solution I came up is ^(.+(?=c$)|.+(?!c$)). However, Lua does not have lookahead, so I'm thinking if there is a way to reduce this to something that Lua natively supports.

4 Answers

You can use (string.match(str:reverse(), "^c(.+)") or str:reverse()):reverse(). If nothing is matched, then the original string is returned.

[Updated to fix the logic]

You can use "s:match("([^c]+c?[^c]*)c$") or s, this will get all non-c characters then potentially a c followed by any remaining non-c characters and the final c if present, in the event of no match it returns the whole string.

Here is an example:

strs = {
  "abc",
  "acc",
  "abd",
  "abcd",
}

for _,s in ipairs(strs) do
  print(s, s:match("([^c]+c?[^c]*)c$") or s)
end

Output:

abc    ab
acc    ac 
abd    abd
abcd   abcd

You can use a capture group to capture 1 more occurrences of any char except c followed by optional c chars.

Then match a c char at the end of the string outside of the group.

([^c]+c*)c$

The pattern matches

  • ( Capture group 1
    • [^c]+c* Match 1+ times any char except c followed by matching optional c chars
  • ) Close group 1
  • c$ Match a c chat at the end of the string

Regex demo

In the code, you can print the value of group 1 if it exists, else print the whole string if there is not match.

I have no experience in Lua, but looking at the code (and borrowing it for an example) posted by @Nifim this would match:

strs = {
  "abc",
  "acc",
  "abd",
  "abcd",
  "c"
}

for _,s in ipairs(strs) do
  print(s:match("([^c]+c*)c$") or s)
end

Output

ab
ac
abd
abcd
c

Egor Skriptunoff provided the best answer in my opinion in the comment here. Since he didn't leave it as dedicated answer, I'll close this question for him. I do not hold any credit.

Original answer:

s:match("(.-)c?$")
Related