This loop implementation loops over arguments in the form of somename1, somename2. It only expands wikitext afterwards which makes it safe to use with categories and other templates.
Usage:
{{ #invoke:Loop | arguments | myArgumentName | [[Category:{{{myArgumentName$n$}}}]] }}
resulting in effectively
{{#if: {{{myArgumentName1|}}}|[[Category:{{{myArgumentName1}}}]]| }}
{{#if: {{{myArgumentName2|}}}|[[Category:{{{myArgumentName2}}}]]| }}...
Script error: Lua error: Internal error: The interpreter exited with status 127.
local p = {} --p stands for package function p.arguments( frame ) local argumentName = frame.args[1] argumentName = mw.ustring.match(argumentName, "^%s*(.-)%s*$") -- trim spaces local text = frame.args[2] -- collect keys and order them local keys = {} for k in pairs(frame:getParent().args) do local from, to, match = string.find(k, "^"..argumentName.."(%d+)$") if from ~= nil then table.insert(keys, tonumber(match)) end end table.sort(keys) local result = ""; for i = 1, #keys do local name = argumentName..keys[i] local parsed = mw.ustring.gsub( text, "{{{ *"..argumentName.." *}}}", "{{{"..name .."}}}" ) parsed = mw.ustring.gsub( parsed, "{{{ *"..argumentName.."%$n%$ *}}}", "{{{"..name.."}}}" ) result = result .. "{{#if: {{{"..name.."|}}}|"..parsed.."| }}" end return frame:getParent():preprocess(result) end function p.matches( frame ) local input = frame.args[1] local pattern = frame.args[2] local replace = frame.args[3] local result = ""; for match in mw.ustring.gmatch(input, pattern) do result = result .. mw.ustring.gsub(replace, "%%1", match); end return frame:getParent():preprocess(result) end return p