string

String functions, patterns and string.format of Lua 5.1 / LuaJIT 2.1.

String functions of Lua 5.1 / LuaJIT 2.1, also callable as methods (("abc"):upper()), with 1-based indices where negative values count from the end.

At a glance

Function Description
string.byte, string.char character codes to and from strings
string.find, string.match, string.gmatch search with patterns
string.gsub replace with patterns
string.format printf-style formatting
string.sub, string.rep, string.reverse slice, repeat, reverse
string.len, string.lower, string.upper length and ASCII case
string.dump bytecode of a function, cannot be loaded back here

Strings are byte strings: lengths and indices count bytes, and lower and upper only change ASCII letters. require("string.buffer") gives the LuaJIT string buffer library, useful to build large strings without creating many intermediate ones.


Functions

string.byte(s, i, j): number

string.byte(s: string, i?: number = 1, j?: number = i): ...number
Name Type Description
s string source
i, j number first and last index

Returns: the codes (0 to 255) of s[i] to s[j], nothing for an empty range.

print(string.byte("ABC", 1, 3))

string.char(...): string

string.char(...: number): string
Name Type Description
... number character codes, 0 to 255

Returns: the string made of these characters. Errors: bad argument #1 to 'char' (invalid value) for a code out of range.

print(string.char(72, 105))

string.dump(f, strip): string

string.dump(f: function, strip?: boolean): string
Name Type Description
f function a Lua function
strip boolean removes debug information

Returns: the bytecode of f. load and loadstring refuse it in this VM (attempt to load chunk with wrong mode), see the sandbox. Errors: unable to dump given function for a C function.

string.find(s, pattern, init, plain): number, number, ...string

string.find(s: string, pattern: string, init?: number = 1, plain?: boolean = false): number, number, ...string
Name Type Description
s string subject
pattern string pattern, or plain text with plain
init number start index
plain boolean true searches pattern as a plain substring

Returns: the start and end index of the first match and its captures, or nil. Errors: malformed pattern (ends with '%') and the other pattern errors.

print(string.find("hello world", "wor"))
print(string.find("a.b", ".", 1, true))

string.format(fmt, ...): string

string.format(fmt: string, ...: any): string
Name Type Description
fmt string text with specifiers
... any one value per specifier

Returns: fmt with each specifier replaced by the next value. Errors: invalid option '%y' to 'format' for an unknown specifier or a width above 99, bad argument #2 to 'format' (number expected, got string) for a wrong type, bad argument #2 to 'format' (value expected) when a value is missing.

print(string.format("%5.2f|%-5d|%s|%x", 3.14159, 42, "x", 255))

string.gmatch(s, pattern): function

string.gmatch(s: string, pattern: string): function(): ...string
Name Type Description
s string subject
pattern string pattern

Returns: an iterator giving the captures of each successive match, or the whole match without captures. A ^ at the start of pattern is not an anchor here, it matches a literal ^.

for word in string.gmatch("one two three", "%a+") do
    print(word)
end

string.gsub(s, pattern, repl, n): string, number

string.gsub(s: string, pattern: string, repl: string | table | function, n?: number): string, number
Name Type Description
s string subject
pattern string pattern
repl string, table or function replacement, see below
n number maximum number of replacements
  • string: %1 to %9 insert a capture, %0 the whole match, %% a %
  • table: indexed with the first capture, or the whole match
  • function: called with the captures, or the whole match
  • a false or nil result keeps the original text

Returns: the new string and the number of matches. Errors: invalid capture index for a %n without capture n.

print(string.gsub("hello world", "o", "0"))
print(string.gsub("$name is $age", "%$(%w+)", { name = "Bob", age = 30 }))

string.len(s): number

string.len(s: string): number
Name Type Description
s string string

Returns: the length in bytes, embedded zeros included. Same as #s.

string.lower(s): string

string.lower(s: string): string
Name Type Description
s string string

Returns: s with ASCII uppercase letters in lowercase.

string.match(s, pattern, init): string | number

string.match(s: string, pattern: string, init?: number = 1): ...string | number
Name Type Description
s string subject
pattern string pattern
init number start index

Returns: the captures of the first match, or the whole match without captures, or nil. A position capture () gives a number.

print(string.match("key=value", "(%w+)=(%w+)"))

string.rep(s, n, sep): string

string.rep(s: string, n: number, sep?: string): string
Name Type Description
s string string to repeat
n number count; 0 or less gives ""
sep string separator between copies (LuaJIT extension)

Returns: s repeated n times.

print(("ab"):rep(3, ", "))

string.reverse(s): string

string.reverse(s: string): string
Name Type Description
s string string

Returns: s with its bytes in reverse order.

string.sub(s, i, j): string

string.sub(s: string, i: number, j?: number = -1): string
Name Type Description
s string string
i number first index, required
j number last index, inclusive

Returns: the substring from i to j, "" for an empty range.

print(string.sub("hello", 2, -2))

string.upper(s): string

string.upper(s: string): string
Name Type Description
s string string

Returns: s with ASCII lowercase letters in uppercase.


Patterns

A pattern is a sequence of items; a single character class matches one character.

Character classes

Class Matches
. any character
%a letters
%c control characters
%d digits
%g printable characters except space
%l lowercase letters
%p punctuation
%s whitespace
%u uppercase letters
%w letters and digits
%x hexadecimal digits
%z the character \0
%A %C %D %G %L %P %S %U %W %X %Z the complement of the lowercase class
% and a non-alphanumeric character that character (%., %%, %()
[set] any character in the set; ranges like a-z and classes like %d are allowed
[^set] any character not in the set

Repetition

Item Meaning
x* zero or more, as many as possible
x+ one or more, as many as possible
x- zero or more, as few as possible
x? zero or one

Anchors and captures

  • ^ at the start anchors the match at init, $ at the end anchors it at the end of the subject.
  • (...) is a capture, numbered by its opening parenthesis. () captures the current position as a number.
  • %b() matches a balanced pair; any two distinct characters work (%bxy).
  • %f[set] is a frontier: an empty match where the previous character is not in set and the next one is.
  • %1 to %9 match a copy of an earlier capture.
print(string.match("f(a(b)c)d", "%b()"))
print(string.gsub("THE (quick) fox", "%f[%a]%a+", string.lower))
print(string.match("say 'hi' now", "(['\"])(.-)%1"))

Format

Specifiers have the form %[flags][width][.precision]type. Flags are -, +, space, # and 0; width and precision have at most 2 digits.

Specifier Value and output
%d, %i integer; a fraction is truncated
%u unsigned integer
%c character with the given code
%x, %X integer in hexadecimal
%o integer in octal
%e, %E number in exponent notation
%f number in fixed-point notation
%g, %G number in the shorter of %e and %f
%a, %A number in hexadecimal floating point
%q string quoted so the Lua parser can read it back
%s string; other values go through __tostring or tostring
%p address of a table, function, thread or userdata
%% a %

Complete example

Parse key=value lines, then print an aligned table.

local text = "name=Steve\nhealth=20\n# comment\nspeed=0.1\n"

local settings, keys = {}, {}
for line in text:gmatch("[^\n]+") do
    local key, value = line:match("^%s*([%w_]+)%s*=%s*(.-)%s*$")
    if key ~= nil then
        settings[key] = tonumber(value) or value
        keys[#keys + 1] = key
    end
end

table.sort(keys)
for _, key in ipairs(keys) do
    print(string.format("%-8s %s", key, tostring(settings[key])))
end
print(("-"):rep(16), ("%q"):format("a \"quoted\" line"))