I don’t believe Lua’s string matching capabilities can solve this alone. Initially, my thought was to do something like %d+[%+%-%*]%d+([%+%-%*]%d+)*
. In other words, match number, operator, number
, and then optionally, more operator, number
patterns (using parentheses notation, but that’s not a thing, sadly). Unfortunately, Lua’s patterns don’t let you repeat patterns/strings (only characters), which renders the matching additional operator, number
patterns part impossible. The alternative I found was to manually get more operator, number
patterns like so:
local function Match(String)
local Substring = ""
local Start, End = string.find(String, "%d+[%+%-%*]%d+") --> find the initial number, operator, number pattern
if Start then
Substring = String:sub(Start, End)
while true do
Start, End = string.find(String, "^[%+%-%*]%d+", End + 1) --> find additional operator, number patterns, ensuring that the patterns come one after the other
if Start then
Substring = Substring .. String:sub(Start, End)
else
break
end
end
return Substring
else
return nil
end
end
print(Match("2+67*36-45")) --> 2+67*36-45
print(Match("2++67*45++5")) --> 67*45
print(Match("2+67**45")) --> 2+67
print(Match("2")) --> nil
print(Match("5+5+")) --> 5+5
I’m not sure how you would like to handle weird string expressions (see the second and third examples in my code). The way I have it is that it’ll find any number, operator, number
pattern and start looking for additional operator, number
patterns from there (strictly making sure that these patterns come one after another, and stopping when this behavior is interrupted). This behavior can be modified to check that the initial number, operator, number
must come first (and with additional end checks, you can make it so that only correct expressions are accepted). You can also modify the string patterns to accept negative numbers (%-?
before the %d+
).
Here’s an example that will only accept valid input (returns nil for invalid expressions):
local function StrictMatch(String)
local Substring = ""
local Start, End = string.find(String, "^%d+[%+%-%*]%d+") --> find the initial number, operator, number pattern
if Start then
Substring = String:sub(Start, End)
while true do
if End == #String then
return Substring
end
Start, End = string.find(String, "^[%+%-%*]%d+", End + 1) --> find additional operator, number patterns, ensuring that the patterns exist at the beginning
if Start then
Substring = Substring .. String:sub(Start, End)
else
return nil
end
end
return Substring
else
return nil
end
end
print(StrictMatch("2+67*36-45")) --> 2+67*36-45
print(StrictMatch("4+555")) --> 4+555
print(StrictMatch("2++67*45++5")) --> nil
print(StrictMatch("2+67**45")) --> nil
print(StrictMatch("2")) --> nil
print(StrictMatch("5+5+")) --> nil
I’m curious to see if there’s a more elegant solution though! Hopefully I didn’t overlook anything.