8
\$\begingroup\$

I have again 2 functions but this time they return either the full file name with extension or just the extension with a dot.

Both actions are so similar that I just copy pasted the code from one and changed 1 character... but at the inside I am cringing because it looks terrible to just copy paste. In addition I am not sure if my way of doing it is good and efficient?

-- Return everything until first forward slash starting at the end. http://my.image.com/bla.jpg would return bla.jpg
function GetFileName(url)
  local str = url
  local temp = ""
  local result = ""

  -- Get file name + extension until first forward slash (/) and then break
  for i = str:len(), 1, -1 do
    if str:sub(i,i) ~= "/" then
      temp = temp..str:sub(i,i)
    else
      break
    end
  end

  -- Reverse order of full file name
  for j = temp:len(), 1, -1 do
    result = result..temp:sub(j,j)
  end

  return result
end

-- Get the extension of a string determined by a dot . at the end of the string.
function GetFileExtension(url)
    local str = url
  local temp = ""
  local result = "." -- ! Remove the dot here to ONLY get the extension, eg. jpg without a dot. The dot is added because Download() expects a file type with a dot.

  for i = str:len(), 1, -1 do
    if str:sub(i,i) ~= "." then
      temp = temp..str:sub(i,i)
    else
      break
    end
  end

  -- Reverse order of full file name
  for j = temp:len(), 1, -1 do
    result = result..temp:sub(j,j)
  end

  return result
end

Usage:

print(GetfileName("http://mypath.to.my.image/image.jpg"))
print(GetFileExtension("http://mypath.to.my.image/image.jpg"))

Result:

image.jpg
.jpg

What would be a better approach or is this as good as it goes? (I highly doubt that. :))

\$\endgroup\$
11
\$\begingroup\$

You are doing too much work manually. It's so much easier and more powerful to use pattern matching.

The two functions can be written as one-liners:

function GetFileName(url)
  return url:match("^.+/(.+)$")
end

function GetFileExtension(url)
  return url:match("^.+(%..+)$")
end

In the patterns, .+ matches one or more any characters as much as possible (greedy). / matches itself, %. matches the dot .. ^ and $ are the anchors for beginning and ending of a string respectively.

\$\endgroup\$
3
  • 2
    \$\begingroup\$ GetFileExtension would give incorrect result for http://example.com/path/image_without_extension \$\endgroup\$ – Egor Skriptunoff Jun 25 '15 at 20:51
  • \$\begingroup\$ But would get correct results with: return GetFileName(url):match("^.+(%..+)$") \$\endgroup\$ – Jesse Chisholm Mar 22 '18 at 17:15
  • 1
    \$\begingroup\$ GetFileName doesn't work properly if the name is given without any slashes; you get nil back. \$\endgroup\$ – frabjous Jan 19 '19 at 10:54
6
\$\begingroup\$

Since you want to get everything from the end, until first / or . are found; use a lua-pattern.

While Yu Hao's suggested pattern would give you the desired results; you can also use the following:

url:match "[^/]+$" -- To match file name
url:match "[^.]+$" -- To match file extension
url:match "([^/]-([^.]+))$" -- To match file name + file extension
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.