I can see this as a series of 3 string.gsub() calls:
("Hello World. Test lua."):gsub("(%S%S%S)","%1!"):gsub("(%s)(%S)","%1!%2"):gsub("^(%S)","!%1");
The first call processes splitting the words into groups of 3 letters separated by "!". This needs to be done first as the other replacements will screw up the grouping pattern. The second pattern handles the start of words by inserting the separator between any occurrence of a space followed by a non-space. The third handles an exception that would rise when the string starts with a non-space character.