Skip to content
String Patterns and Performance
step 1/5

Reading — step 1 of 5

Learn

~2 min readSandboxing and Embedding

Lua doesn't have full regex — it has its own pattern syntax. Smaller, faster, less expressive.

Character classes:

  • %a — letters
  • %d — digits
  • %s — whitespace
  • %w — alphanumeric
  • %p — punctuation
  • %l / %u — lower / upper case
  • %c — control characters

Uppercase versions are negation: %A = non-letter.

Quantifiers (more limited than regex):

  • * — 0 or more (greedy)
  • + — 1 or more (greedy)
  • - — 0 or more (NON-greedy)
  • ? — 0 or 1

No {n,m} ranges.

Anchors: ^ start, $ end. Inside [...], ^ means negation.

Captures with ():

local date = "2026-05-08"
local y, m, d = string.match(date, "(%d+)-(%d+)-(%d+)")
print(y, m, d)   -- 2026  05  08

string.gmatch — iterator over all matches:

for word in string.gmatch("the quick brown fox", "%w+") do
    print(word)
end

string.gsub — replace (returns new string + count):

local result, n = string.gsub("hello world", "%w+", "X")
print(result, n)   -- X X  2

With capture in replacement: %1, %2, ...

string.gsub("hello world", "(%w+)", "<%1>")
-- "<hello> <world>"

Performance tips:

  • Lua patterns are MUCH faster than typical regex
  • String concatenation a .. b is O(n+m) every time — for many concats use table.concat:
local parts = {}
for i = 1, 1000 do
    parts[#parts + 1] = tostring(i)
end
local result = table.concat(parts, ",")
  • Local variables are MUCH faster than globals — avoid hot-path globals:
local print = print     -- cache the global once
for i = 1, n do print(i) end
  • Avoid creating tables in tight loops — pre-allocate:
local buf = {}
for i = 1, n do buf[i] = compute(i) end

LuaJIT is dramatically faster than reference Lua for tight numerical code.

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…