| title | description |
|---|---|
Strings |
A sequence of characters, such as letters, numbers, and symbols. |
The string data type is a sequence of characters, such as letters, numbers, and symbols. It's the data type for storing most text-based information.
To declare a string variable, put quotes around the characters. It's more common to use double quotes ("), but single quotes (') also work. If you want to include a single or double quote in your string, wrap your string around the other type of quote, or use an escaped quote.
local string1 = "Hello world!"
print(string1) --> Hello world!
local string2 = 'Hello "world"!'
print(string2) --> Hello "world"!To include both single and double quotes in a string, or to create multi-line strings, declare them using double brackets:
local string1 = [[Hello
world!
Hello "world"!
Hello 'world'!]]
print(string1)
--> Hello
--> world!
--> Hello "world"!
--> Hello 'world'!If necessary, you can nest multiple brackets inside a string using the same number of equal signs in both the beginning and ending bracket:
local string1 = [=[Hello
[[world!]]
]=]
print(string1)
--> Hello
--> [[world!]]To combine strings, concatenate them with two dots (..). Concatenating strings doesn't insert a space between them, so you'll need to include space(s) at the end/beginning of a preceding/subsequent string, or concatenate a space between the two strings.
local hello = "Hello"
local helloWithSpace = "Hello "
local world = "world!"
local string1 = hello .. world
local string2 = helloWithSpace .. world
local string3 = hello .. " " .. world
print(string1) --> Helloworld!
print(string2) --> Hello world!
print(string3) --> Hello world!Note that the print() command takes multiple arguments and combines them with spaces, so you can use , instead of .. to yield spaces in print() outputs.
local hello = "Hello"
local world = "world"
local exclamationMark = "!"
print(hello .. world .. exclamationMark) --> Helloworld!
print(hello, world .. exclamationMark) --> Hello world!
print(hello, world, exclamationMark) --> Hello world !To convert a string to a number, use the Global.LuaGlobals.tonumber() function. If the string doesn't have a number representation, Global.LuaGlobals.tonumber() returns nil.
local numericString = "123"
print(tonumber(numericString)) --> 123
local alphanumericString = "Hello123"
print(tonumber(alphanumericString)) --> nilTo escape a double- or single-quote string declaration and embed almost any character, put a backslash (\) before the character. For example:
- To embed a single quote in a single-quote string, use
\'. - To embed a double quote in a double-quote string, use
\".
local string1 = 'Hello \'world\'!'
print(string1) --> Hello 'world'!
local string2 = "Hello \"world\"!"
print(string2) --> Hello "world"!Certain characters following backslashes produce special characters rather than escaped characters:
- To embed a new line, use
\n. - To embed a horizontal tab, use
\t.
local string1 = "Hello\nworld!"
print(string1)
--> Hello
--> world!
local string2 = "Hello\tworld!"
print(string2) --> Hello world!Luau supports string interpolation, a feature that lets you insert expressions into strings. Use backticks (`) to declare an interpolated string, then add expressions inside of curly brackets:
local world = "world"
local string1 = `Hello {world}!`
print(string1) --> Hello world!Although variables are the most common usage, you can use any expression, including math:
local world = "world"
local number = 1
local letters = {"w", "o", "r", "l", "d"}
local string1 = `Hello {world}, {number} time!`
local string2 = `Hello {world}, {number + 1} times!`
local string3 = `Hello {table.concat(letters)} a third time!`
print(string1) --> Hello world, 1 time!
print(string2) --> Hello world, 2 times!
print(string3) --> Hello world a third time!Standard escape rules apply for backticks, curly brackets, and backslashes:
local string1 = `Hello \`\{world\}\`!`
print(string1) --> Hello `{world}`!If you perform math operations on a string, Luau automatically converts the string to a number. If the string doesn't have a number representation, it throws an error.
print("55" + 10) --> 65
print("55" - 10) --> 45
print("55" * 10) --> 550
print("55" / 10) --> 5.5
print("55" % 10) --> 5
print("Hello" + 10) --> print("Hello" + 10):1: attempt to perform arithmetic (add) on string and numberStrings can be compared using the <, <=, > and >= operators which compare using lexicographical order based on the ASCII codes of each character in a string.
This will result in numbers in strings not being compared correctly, for example, "100" will be less than "20", since the bytes "0" and "1" have lower ASCII codes than byte "2".
print("Apple" < "apple") --> true
print("Banana" < "apple") --> true (B is before a in ASCII)
print("number100" < "number20") --> trueA string pattern is a combination of characters that you can use with
Library.string.match(), Library.string.gmatch(), and other functions to
find a piece, or substring, of a longer string.
You can use direct matches in a Luau function like Library.string.match(),
except for magic characters. For example, these commands
look for the word Roblox within a string:
local match1 = string.match("Welcome to Roblox!", "Roblox")
local match2 = string.match("Welcome to my awesome game!", "Roblox")
print(match1) --> Roblox
print(match2) --> nilCharacter classes are essential for more advanced string searches. You can use them to search for something that isn't necessarily character-specific but fits within a known category (class), including letters, digits, spaces, punctuation, and more.
The following table shows the official character classes for Luau string patterns:
| Class | Represents | Example Match |
|---|---|---|
. |
Any character | 32kasGJ1%fTlk?@94 |
%a |
An uppercase or lowercase letter | aBcDeFgHiJkLmNoPqRsTuVwXyZ |
%l |
A lowercase letter | abcdefghijklmnopqrstuvwxyz |
%u |
An uppercase letter | ABCDEFGHIJKLMNOPQRSTUVWXYZ |
%d |
Any digit (number) | 0123456789 |
%p |
Any punctuation character | !@#;,. |
%w |
An alphanumeric character (either a letter or a number) | aBcDeFgHiJkLmNoPqRsTuVwXyZ0123456789 |
%s |
A space or whitespace character | , \n, and \r |
%c |
A special control character | |
%x |
A hexadecimal character | 0123456789ABCDEF |
%z |
The NULL character (\0) |
For single-letter character classes such as %a and %s, the corresponding
uppercase letter represents the "opposite" of the class. For instance, %p
represents a punctuation character while %P represents all characters except
punctuation.
There are 12 "magic characters" which are reserved for special purposes in patterns:
$ |
% |
^ |
* |
( |
) |
. |
[ |
] |
+ |
- |
? |
You can escape and search for magic characters using the % symbol. For
example, to search for roblox.com, escape the . (period) symbol by
preceding it with a % as in %..
-- "roblox.com" matches "roblox#com" because the period is interpreted as "any character"
local match1 = string.match("What is roblox#com?", "roblox.com")
print(match1) --> roblox#com
-- Escape the period with % so it is interpreted as a literal period character
local match2 = string.match("I love roblox.com!", "roblox%.com")
print(match2) --> roblox.comYou can search for a pattern at the beginning or end of a string by using the
^ and $ symbols.
local start1 = string.match("first second third", "^first") -- Matches because "first" is at the beginning
print(start1) --> first
local start2 = string.match("third second first", "^first") -- Doesn't match because "first" isn't at the beginning
print(start2) --> nil
local end1 = string.match("first second third", "third$") -- Matches because "third" is at the end
print(end1) --> third
local end2 = string.match("third second first", "third$") -- Doesn't match because "third" isn't at the end
print(end2) --> nilYou can also use both ^ and $ together to ensure a pattern matches only
the full string and not just some portion of it.
-- Using both ^ and $ to match across a full string
local match1 = string.match("Roblox", "^Roblox$") -- Matches because "Roblox" is the entire string (equality)
print(match1) --> Roblox
local match2 = string.match("I play Roblox", "^Roblox$") -- Doesn't match because "Roblox" isn't at the beginning AND end
print(match2) --> nil
local match3 = string.match("I play Roblox", "Roblox") -- Matches because "Roblox" is contained within "I play Roblox"
print(match3) --> RobloxBy itself, a character class only matches one character in a string. For
instance, the following pattern ("%d") starts reading the string from left
to right, finds the first digit (2), and stops.
local match = string.match("The Cloud Kingdom has 25 power gems", "%d")
print(match) --> 2You can use modifiers with any character class to control the result:
| Quantifier | Meaning |
|---|---|
+ |
Match 1 or more of the preceding character class |
- |
Match as few of the preceding character class as possible |
* |
Match 0 or more of the preceding character class |
? |
Match 1 or less of the preceding character class |
%n |
For n between 1 and 9, matches a substring equal to the nth captured string. |
%bxy |
The balanced capture matching x, y, and everything between (for example, %b() matches a pair of parentheses and everything between them) |
Adding a modifier to the same pattern ("%d+" instead of "%d"), outputs
25 instead of 2:
local match1 = string.match("The Cloud Kingdom has 25 power gems", "%d")
print(match1) --> 2
local match2 = string.match("The Cloud Kingdom has 25 power gems", "%d+")
print(match2) --> 25Sets should be used when a single character class can't do the whole job.
For instance, you might want to match both lowercase letters (%l) and
punctuation characters (%p) using a single pattern.
Sets are defined by brackets [] around them. In the following example,
notice the difference between using a set ("[%l%p]+") and not using a
set ("%l%p+").
local match1 = string.match("Hello!!! I am another string.", "[%l%p]+") -- Set
print(match1) --> ello!!!
local match2 = string.match("Hello!!! I am another string.", "%l%p+") -- Non-set
print(match2) --> o!!!The first command (set) tells Luau to find both lowercase characters and
punctuation. With the + quantifier added after the entire set, it finds
all of those characters (ello!!!), stopping when it reaches the space.
In the second command (non-set), the + quantifier only applies to the %p
class before it, so Luau grabs only the first lowercase character (o) before
the series of punctuation (!!!).
Like character classes, sets can be "opposites" of themselves. This is done by
adding a ^ character at the beginning of the set, directly after the opening
[. For instance, "[%p%s]+" represents both punctuation and spaces, while
"[^%p%s]+" represents all characters except punctuation and spaces.
Sets also support ranges which let you find an entire range of matches between a starting and ending character. This is an advanced feature which is outlined in more detail on the Lua 5.1 Manual.
String captures are sub-patterns within a pattern. These are enclosed in
parentheses () and are used to get (capture) matching substrings and save
them to variables. For example, the following pattern contains two captures,
(%a+) and (%d+), which return two substrings upon a successful match.
local pattern = "(%a+)%s?=%s?(%d+)"
local key1, val1 = string.match("TwentyOne = 21", pattern)
print(key1, val1) --> TwentyOne 21
local key2, val2 = string.match("TwoThousand= 2000", pattern)
print(key2, val2) --> TwoThousand 2000
local key3, val3 = string.match("OneMillion=1000000", pattern)
print(key3, val3) --> OneMillion 1000000The ? quantifier that follows both of the %s classes is a safe addition
because it makes the space on either side of the = sign optional. That means
the match succeeds if one (or both) spaces are missing around the equal sign.
In the Library.string.gsub() function, you can include capture groups in the
replacement string using %1, %2, %3, etc., up to %9. Even though Luau
supports up to 32 capture groups before throwing an error, you can only
reference the first nine with this syntax:
local str = "love2play Roblox"
local pattern = "(%w+)(%d+)(%w+)%s+(%w+)"
local replacement = "I %1 %2 %3 %4!"
local result = string.gsub(str, pattern, replacement)
print(result) --> I love 2 play Roblox!You can also nest string captures:
local places = "The Cloud Kingdom is heavenly, The Forest Kingdom is peaceful"
local pattern = "(The%s(%a+%sKingdom)[%w%s]+)"
for description, kingdom in string.gmatch(places, pattern) do
print(description)
print(kingdom)
end
--> The Cloud Kingdom is heavenly
--> Cloud Kingdom
--> The Forest Kingdom is peaceful
--> Forest KingdomThis pattern search works as follows:
The Library.string.gmatch() iterator looks for a match on the entire
"description" pattern defined by the outer pair of parentheses. This stops at
the first comma and captures the following:
| # | Pattern | Capture |
|---|---|---|
| 1 | (The%s(%a+%sKingdom)[%w%s]+) |
The Cloud Kingdom is heavenly |
Using its successful first capture, the iterator then looks for a match on the "kingdom" pattern defined by the inner pair of parentheses. This nested pattern simply captures the following:
| # | Pattern | Capture |
|---|---|---|
| 2 | (%a+%sKingdom) |
Cloud Kingdom |
The iterator then backs out and continues searching the full string, capturing the following:
| # | Pattern | Capture |
|---|---|---|
| 3 | (The%s(%a+%sKingdom)[%w%s]+) |
The Forest Kingdom is peaceful |
| 4 | (%a+%sKingdom) |
Forest Kingdom |
In addition to all of the above, there is a special case with an empty capture (()). If a capture is empty, then the position in the string will be captured:
local match1 = "Where does the capture happen? Who knows!"
local match2 = "This string is longer than the first one. Where does the capture happen? Who knows?!"
local pattern = "()Where does the capture happen%? Who knows!()"
local start1, finish1 = string.match(match1, pattern)
print(start1, finish1) --> 1 42
local start2, finish2 = string.match(match2, pattern)
print(start2, finish2) --> 43 84These special captures may be nested like normal ones:
local places = "The Cloud Kingdom is heavenly, The Forest Kingdom is peaceful."
local pattern = "The (%a+()) Kingdom is %a+"
for kingdom, position in string.gmatch(places, pattern) do
print(kingdom, position)
end
--> Cloud 10
--> Forest 42The returned values are unusual in that they are numbers rather than strings:
local match = "This is an example"
local pattern = "This is an ()example"
local position = string.match(match, pattern)
print(typeof(position)) --> number