0Pricing
Lua Academy · Lesson

Finding and Extracting Substrings

Apply string.find and string.sub to locate and extract text.

Finding and Extracting Substrings is a free Lua Academy lesson on CoddyKit — lesson 2 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Lua Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

string.find Basics

string.find(s, pattern, init, plain) searches for a pattern in s starting at init (default 1). It returns the start and end positions of the match, or nil if not found. With plain=true, it treats the pattern as a literal string (no magic characters).

local s = "hello world"
local i, j = string.find(s, "world")
print(i, j)    -- 7  11

-- Plain search (literal string)
local i2, j2 = string.find("a+b=5", "+", 1, true)
print(i2, j2)  -- 2  2

-- Not found
print(string.find(s, "xyz"))  -- nil

string.sub for Extraction

string.sub(s, i, j) extracts the substring from position i to j (inclusive). Negative indices count from the end: -1 is the last character. If j is omitted, it defaults to the end of the string.

local s = "hello world"
print(string.sub(s, 1, 5))    -- hello
print(string.sub(s, 7))       -- world
print(string.sub(s, -5))      -- world
print(string.sub(s, 1, -7))   -- hello
print(s:sub(7, 11))           -- world (method syntax)

Combining find and sub

Combine string.find and string.sub to locate and extract substrings. First find the delimiter, then extract the parts around it. This is the basic string-splitting approach.

local s = "key=value"
local i = string.find(s, "=")
if i then
  local key = string.sub(s, 1, i - 1)
  local val = string.sub(s, i + 1)
  print(key, val)   -- key  value
end

string.match for Pattern Capture

string.match(s, pattern, init) returns the captured substrings matching the pattern. If the pattern has no captures, it returns the whole match. If nothing matches, it returns nil. Captures are defined with parentheses in the pattern.

local date = "2024-03-15"
local y, m, d = string.match(date, "(%d+)-(%d+)-(%d+)")
print(y, m, d)   -- 2024  03  15

-- No capture: returns the whole match
local num = string.match("price: 42.5 USD", "%d+%.%d+")
print(num)       -- 42.5

Finding Last Occurrence

To find the last occurrence of a substring, search with a loop advancing the start position, or search from the end. The standard approach: keep calling string.find with the position just past the previous match until it returns nil.

local function findLast(s, sub)
  local last_i, last_j
  local i, j = string.find(s, sub, 1, true)
  while i do
    last_i, last_j = i, j
    i, j = string.find(s, sub, j + 1, true)
  end
  return last_i, last_j
end

local i, j = findLast("a/b/c/d", "/")
print(i, j)   -- 6  6

Extracting File Extensions

A practical use of string.match: extract the extension from a filename. The pattern "([^%.]+)$" captures the last non-dot sequence at the end of the string, or "%.([^%.]+)$" to capture just after the last dot.

local function getExt(filename)
  return string.match(filename, "%.([^%.]+)$")
end

print(getExt("photo.jpg"))        -- jpg
print(getExt("archive.tar.gz"))   -- gz
print(getExt("README"))           -- nil
print(getExt("config.lua.bak"))   -- bak

Splitting Strings

Lua has no built-in string split, but you can implement one with string.gmatch. Iterate over all non-delimiter sequences or use a pattern that captures between delimiters.

local function split(s, sep)
  local result = {}
  local pattern = "([^" .. sep .. "]+)"
  for part in string.gmatch(s, pattern) do
    result[#result+1] = part
  end
  return result
end

local parts = split("one,two,three,four", ",")
for i, p in ipairs(parts) do
  print(i, p)
end
-- 1 one  2 two  3 three  4 four

Trimming Whitespace

Remove leading and trailing whitespace by matching and discarding it. The pattern "^%s*(.-)%s*$" uses a lazy quantifier .- to capture the minimal content between optional leading/trailing spaces.

local function trim(s)
  return string.match(s, "^%s*(.-)%s*$")
end

print("|" .. trim("  hello  ") .. "|")  -- |hello|
print("|" .. trim("  \t\n") .. "|")    -- ||
print("|" .. trim("no spaces") .. "|")  -- |no spaces|

Extracting Numbers from Text

Use string.gmatch with a number pattern to extract all numbers from a string. The pattern %-?%d+%.?%d* matches optional negative sign, digits, optional decimal point, and more digits.

local text = "Revenue: $1,234.56 Expenses: $567.89 Net: $666.67"
local numbers = {}
for n in string.gmatch(text, "%d+%.?%d*") do
  numbers[#numbers+1] = tonumber(n)
end
for _, v in ipairs(numbers) do
  io.write(v .. " ")
end
print()  -- 1 234.0 56.0 567.89 666.67

String Position Normalization

Lua's negative indices let you work from the end of a string. string.sub(s, -n) gets the last n characters. Combine with #s to compute positions. Understanding the relationship between positive and negative indices prevents off-by-one bugs.

local s = "abcdefgh"

-- Last 3 characters
print(s:sub(-3))     -- fgh

-- All but last 2
print(s:sub(1, -3))  -- abcdef

-- Character at position from end
print(s:sub(-1, -1)) -- h
print(s:sub(-4, -2)) -- efg

Quick Check

What does string.sub("hello", 2, -2) return?

Recap: Finding and Extracting

Summary:

  • string.find(s, pat, init, plain) — returns start,end or nil
  • string.sub(s, i, j) — extract by position; negative indices from end
  • string.match(s, pat) — return captures or full match
  • Use plain=true for literal search (no magic chars)
  • Implement split with string.gmatch
  • Trim: "^%s*(.-)%s*$" pattern

Frequently asked questions

Is the “Finding and Extracting Substrings” lesson free?

Yes — the full text of “Finding and Extracting Substrings” is free to read here on the web, and the Lua Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Lua Academy course, upgrade to CoddyKit PRO.

What will I learn in “Finding and Extracting Substrings”?

Apply string.find and string.sub to locate and extract text. You practise Lua Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start Lua Academy?

No prior experience is required. Lua Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 2 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Finding and Extracting Substrings” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this Lua Academy lesson?

Yes. Every Lua Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. String Basics: Concat and Length
  2. Finding and Extracting Substrings
  3. string.format for Output
  4. string.gsub and string.gmatch
← Back to Lua Academy