Question about a particular string pattern

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.

3 Likes