Hey gang, I haven't really been active lately, but I started working on some new stuff for myself and had to find a solution for a problem for which I couldn't seem to find a work around. This problem was that while trying to match patterns, I wanted to know where in the string that a match was showing up.

To solve this problem, I wrote an iterator function which uses a combination of string.gmatch and string.find to match all occurrences while also keeping track of where the match comes from in the string.

--[[
		This function behaves just like gmatch, but it also returns the position
	in the line of the match.

	@return iterator function which returns the start, stop, and textual match of every
			occurence of the given pattern.

	Example:
		for start, stop, match in gfind (str, pat) do
			...
		end
]]
local function gfind (_string, pattern)
	if not _string or not pattern then
		error ("Arguments to gfind are invalid: faulty string or pattern.")
	end

	local start, stop;

	return function()
		if stop then
			stop = stop + 1
		end
		start, stop = _string:find (pattern, stop)

		return start, stop, (start ~= nil) and _string:sub (start, stop) or nil
	end
end

This function returns both the start and stop of the match as well as the match itself. This was one of my first experiences writing an iterator function, but I hope it works well for anyone else who might need something like this! :)/>

Example:

local function gfind (_string, pattern)
	if not _string or not pattern then
		error ("Arguments to gfind are invalid: faulty string or pattern.")
	end

	local start, stop;

	return function()
		if stop then
			stop = stop + 1
		end
		start, stop = _string:find (pattern, stop)

		return start, stop, (start ~= nil) and _string:sub (start, stop) or nil
	end
end

local _string  = "This is a string with with a repeat in it."
local lastWord;

for start, stop, match in gfind (_string, "%s-(%w+)%s-") do
	if match == lastWord then
		_string = _string:sub (1, start - 1) .. _string:sub (stop + 1)
	end

	lastWord = match
end

-- Output: This is a string with a repeat in it.
print (_string)
The above example, although probably not that common of an issue and one with more than one solution, goes through the string and locates repeated words which are right next to one another. By using gfind, we can remove the repeated word. However, this is obviously not the best example because there are sentences in English where words are repeated simultaneously for necessity, such as "that that," but I couldn't think of another example quickly off the top of my head which did not require a lot of background (I am using this function in a larger script).

You guys are welcome to use it, but, if you wouldn't mind, please give credit where credit is due. :)/>

Pastebin.