You can look at string pattern captures in the page for string patterns.
A proposed solution would be text:match('^(.-)_'); breaking this down, we know with ^ we match from the start of the string, () means we have a capture which will be returned as a separate variable, and .- will match the least amount of any character it can until it reaches the _ after it. Note that since the _ is not included in the capture, it won’t be returned or anything after it.
I’d use string.find, but it’s the same thing you mentioned. If you use string.find(“_”), you can find the index of where the _ is, then take string.sub(string, 1, index-1) to get everything before it.
Only thing is it won’t support names with _ inside them (eg. Cabin_One_5123456). In that case, you’d need to use string patterns like @AMD_chan mentioned.
If you want to stick with using string.split you can concatenate all the strings after the second one.
local split_result = string.split("/warn User Stop spamming chat please", " ")
-- concatenate strings after the second one in the list with space
print(table.concat(split_result, " ", 3))