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)) --> nil
To 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 number
Strings 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") --> true
A 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) --> nil
Character 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.com
You 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) --> nil
You 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) --> Roblox
By 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) --> 2
You 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 n th 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) --> 25
Sets 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 1000000
In the previous pattern, the ?
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.
String captures can also be nested as the following example:
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 Kingdom
This 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 84
These 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 42
The 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