3

I have a string which can be of any characters. I like to extract only the part between two exclamation marks or before the first or after the last one:

str = "what)ever!when(ver!time!is!mo/ey"

function getStrPart(str,n) -- return a substring
  return str:sub(...) or nil
end

getStrPart(str,0) -- return "what)ever"  -- string until the first !
getStrPart(str,1) -- return "when(ver"   --  between first and second !
getStrPart(str,2) -- return "time"
getStrPart(str,3) -- return "is"
getStrPart(str,4) -- return "mo/ey"
getStrPart(str,5) -- return nil    -- for all n less 0 or > 4 (no of the !)

If the string contains no !

str = "whatever"  

then the function should return nil

wsha
  • 874
  • 2
  • 9
  • 25
Red-Cloud
  • 438
  • 6
  • 13
  • thanks, works fine. Give it as an answer, please – Red-Cloud Oct 06 '18 at 11:08
  • @Herbert: He won't. He unfortunately believes that easy questions should be answered in comments, so that the Lua tag's list of "unanswered" questions is utterly useless for finding questions that are actually unanswered. – Nicol Bolas Oct 06 '18 at 13:15

2 Answers2

2

Your getStrPart function is going to be highly inefficient. Every time you call it, you have to search through the whole string. It would be much better to just return a table containing all of the "string parts" that you index.

Also, Lua uses 1-based indices, so you should stick to that too.

function get_string_parts(str)
  local ret = {}
  for match in str:gmatch("[^!]") do
    if(#match == #str) then --No `!` found in string.
      return ret
    end
    ret[#ret + 1] = match
  end
  return ret
end
Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
  • You are right but in my special case the other solution makes more sense. However, I'll use your one in another situation. Thanks – Red-Cloud Oct 06 '18 at 18:22
2
function getStrPart(str,n) -- return a substring
  if n>=0 then
    return (
      str:gsub("!.*", "%0!")
         :gsub("[^!]*!", "", n)
         :match("^([^!]*)!")
    )
  end
end
Egor Skriptunoff
  • 23,359
  • 2
  • 34
  • 64