字符串数据类型是一系列字符,如字母、数字和符号。它是存储大多数文本信息的数据类型。
声明字符串
要声明一个字符串变量,请将字符放在引号中。使用双引号(")更为常见,但单引号(')也可以。如果要在字符串中包含单引号或双引号,请将字符串用另一种类型的引号括起来,或使用转义引号。
local string1 = "你好,世界!"print(string1) --> 你好,世界!local string2 = '你好 "世界"!'print(string2) --> 你好 "世界"!
要在字符串中同时包含单引号和双引号,或者创建多行字符串,请使用双括号声明它们:
local string1 = [[你好世界!你好 "世界"!你好 '世界'!]]print(string1)--> 你好--> 世界!--> 你好 "世界"!--> 你好 '世界'!
如有必要,您可以在字符串中嵌套多个括号,开始和结束括号中使用相同数量的等号:
local string1 = [=[你好[[世界!]]]=]print(string1)--> 你好--> [[世界!]]
组合字符串
要组合字符串,请用两个点(..)进行连接。连接字符串时不会在它们之间插入空格,因此您需要在前一个/后一个字符串的末尾/开头包含空格,或者在两个字符串之间连接空格。
local hello = "你好"local helloWithSpace = "你好 "local world = "世界!"local string1 = hello .. worldlocal string2 = helloWithSpace .. worldlocal string3 = hello .. " " .. worldprint(string1) --> 你好世界!print(string2) --> 你好 世界!print(string3) --> 你好 世界!
请注意,print()命令接受多个参数并以空格连接它们,因此您可以使用 , 而不是 .. 来得到 print() 输出中的空格。
local hello = "你好"local world = "世界"local exclamationMark = "!"print(hello .. world .. exclamationMark) --> 你好世界!print(hello, world .. exclamationMark) --> 你好 世界!print(hello, world, exclamationMark) --> 你好 世界 !
转换字符串
要将字符串转换为数字,请使用 tonumber() 函数。如果字符串没有数字表示形式,tonumber() 将返回 nil。
local numericString = "123"print(tonumber(numericString)) --> 123local alphanumericString = "你好123"print(tonumber(alphanumericString)) --> nil
转义字符串
要转义双引号或单引号字符串声明并嵌入几乎任何字符,请在字符之前放置反斜杠(\)。例如:
- 要在单引号字符串中嵌入单引号,请使用 \'。
- 要在双引号字符串中嵌入双引号,请使用 \"。
local string1 = '你好 \'世界\'!'print(string1) --> 你好 '世界'!local string2 = "你好 \"世界\"!"print(string2) --> 你好 "世界"!
反斜杠后面的某些字符会产生特殊字符而不是转义字符:
- 要嵌入换行符,请使用 \n。
- 要嵌入水平制表符,请使用 \t。
local string1 = "你好\n世界!"print(string1)--> 你好--> 世界!local string2 = "你好\t世界!"print(string2) --> 你好 世界!
字符串插值
Luau 支持 字符串插值,这是一个允许您将表达式插入字符串的功能。使用反引号 (`) 声明插值字符串,然后在大括号内添加表达式:
local world = "世界"local string1 = `你好 {world}!`print(string1) --> 你好 世界!
虽然变量是最常用的用法,但您可以使用任何表达式,包括数学:
local world = "世界"local number = 1local letters = {"w", "o", "r", "l", "d"}local string1 = `你好 {world}, {number} 次!`local string2 = `你好 {world}, {number + 1} 次!`local string3 = `你好 {table.concat(letters)} 第三次!`print(string1) --> 你好 世界,1 次!print(string2) --> 你好 世界,2 次!print(string3) --> 你好 世界 第三次!
反引号、大括号和反斜杠的标准转义规则适用:
local string1 = `你好 \`\{world\}\`!`print(string1) --> 你好 `{world}`!
数学转换
如果您对字符串执行数学运算,Luau 会自动将字符串转换为数字。如果字符串没有数字表示形式,则会引发错误。
print("55" + 10) --> 65print("55" - 10) --> 45print("55" * 10) --> 550print("55" / 10) --> 5.5print("55" % 10) --> 5print("你好" + 10) --> print("你好" + 10):1: 尝试对字符串和数字执行算术操作(加)
比较
字符串可以使用 <、<=、> 和 >= 运算符进行比较,这些运算符根据字符串中每个字符的 ASCII 代码的字典顺序进行比较。这将导致字符串中的数字不能正确比较,例如,"100" 将小于 "20",因为字节 "0" 和 "1" 的 ASCII 代码低于字节 "2"。
print("苹果" < "苹果") --> trueprint("香蕉" < "苹果") --> true (B 在 ASCII 中在 a 之前)print("number100" < "number20") --> true
字符串模式参考
字符串模式是您可以与 string.match()、string.gmatch() 以及其他函数一起使用的字符组合,以查找更长字符串的一部分或子字符串。
直接匹配
您可以在 Luau 函数中使用直接匹配,例如 string.match(),除了魔法字符。例如,这些命令在字符串中查找 Roblox 这个单词:
local match1 = string.match("欢迎来到 Roblox!", "Roblox")local match2 = string.match("欢迎来到我的超棒游戏!", "Roblox")print(match1) --> Robloxprint(match2) --> nil
字符类
字符类对于更高级的字符串搜索至关重要。您可以使用它们来搜索不是特定字符但属于已知类别(类)的内容,包括 字母、数字、空格、标点符号 等。
下表显示了 Luau 字符串模式的官方字符类:
| 类 | 表示 | 示例匹配 |
|---|---|---|
| . | 任何字符 | 32kasGJ1%fTlk?@94 |
| %a | 一个大写或小写字母 | aBcDeFgHiJkLmNoPqRsTuVwXyZ |
| %l | 一个小写字母 | abcdefghijklmnopqrstuvwxyz |
| %u | 一个大写字母 | ABCDEFGHIJKLMNOPQRSTUVWXYZ |
| %d | 任何数字(数字) | 0123456789 |
| %p | 任何标点符号 | !@#;,. |
| %w | 一个字母数字字符(字母 或 数字) | aBcDeFgHiJkLmNoPqRsTuVwXyZ0123456789 |
| %s | 一个空格或空白字符 | 、\n 和 \r |
| %c | 一个特殊 控制字符 | |
| %x | 一个十六进制字符 | 0123456789ABCDEF |
| %z | 空字符(\0) |
对于单字母字符类,例如 %a 和 %s,对应的大写字母表示类的“相反”。例如,%p 表示标点符号,而 %P 表示所有字符,除标点符号外。
魔法字符
有 12 个“魔法字符”专门保留用于模式中的特殊用途:
| $ | % | ^ | * | ( | ) |
| . | [ | ] | + | - | ? |
您可以使用 % 符号转义和搜索魔法字符。例如,要搜索 roblox.com,请通过在 .(句点)符号前面添加 % 来转义它,如 %.。
-- "roblox.com" 匹配 "roblox#com",因为句点被解释为 "任何字符"local match1 = string.match("roblox#com 是什么?", "roblox.com")print(match1) --> roblox#com-- 使用 % 转义句点,以便将其解释为字面句点字符local match2 = string.match("我爱 roblox.com!", "roblox%.com")print(match2) --> roblox.com
锚点
您可以使用 ^ 和 $ 符号在字符串的开头或结尾搜索模式。
local start1 = string.match("第一个 第二个 第三个", "^第一个") -- 匹配,因为 "第一个" 在开头print(start1) --> 第一个local start2 = string.match("第三个 第二个 第一个", "^第一个") -- 不匹配,因为 "第一个" 不是在开头print(start2) --> nillocal end1 = string.match("第一个 第二个 第三个", "第三个$") -- 匹配,因为 "第三个" 在结尾print(end1) --> 第三个local end2 = string.match("第三个 第二个 第一个", "第三个$") -- 不匹配,因为 "第三个" 不是在结尾print(end2) --> nil
您还可以将 ^ 和 $ 一起使用,以确保模式仅与完整字符串匹配,而不是其部分。
-- 使用 ^ 和 $ 在完整字符串上匹配local match1 = string.match("Roblox", "^Roblox$") -- 匹配,因为 "Roblox" 是整个字符串(相等)print(match1) --> Robloxlocal match2 = string.match("我玩 Roblox", "^Roblox$") -- 不匹配,因为 "Roblox" 既不在开头也不在结尾print(match2) --> nillocal match3 = string.match("我玩 Roblox", "Roblox") -- 匹配,因为 "Roblox" 包含在 "我玩 Roblox" 内print(match3) --> Roblox
类修改符
字符类本身只匹配字符串中的 一个 字符。例如,以下模式("%d")从左到右读取字符串,找到 第一个 数字(2),然后停止。
local match = string.match("云之国有 25 个能量宝石", "%d")print(match) --> 2
您可以使用 修改符 与任何字符类结合使用以控制结果:
| 量词 | 含义 |
|---|---|
| + | 匹配一个或多个前面的字符类 |
| - | 尽可能少地匹配前面的字符类 |
| * | 匹配零个或多个前面的字符类 |
| ? | 匹配一个或更少的前面的字符类 |
| %n | 对于 n 在 1 到 9 之间,匹配与第 n 个捕获字符串相等的子字符串。 |
| %bxy | 匹配平衡捕获的 x、y 及其之间的所有内容(例如,%b() 匹配一对括号及其之间的所有内容) |
将修改符添加到相同的模式("%d+" 而不是 "%d")时,会输出 25 而不是 2:
local match1 = string.match("云之国有 25 个能量宝石", "%d")print(match1) --> 2local match2 = string.match("云之国有 25 个能量宝石", "%d+")print(match2) --> 25
类集合
当单个字符类无法完成整个工作时,应使用 集合。例如,您可能希望使用单个模式匹配小写字母(%l) 和 标点符号字符(%p)。
集合由方括号 [] 包围。在以下示例中,请注意使用集合("[%l%p]+")与不使用集合("%l%p+")之间的差异。
local match1 = string.match("你好!!! 我是另一个字符串。", "[%l%p]+") -- 集合print(match1) --> 你好!!!local match2 = string.match("你好!!! 我是另一个字符串。", "%l%p+") -- 非集合print(match2) --> 呐!!!
第一个命令(集合)告诉 Luau 查找小写字母和标点符号。由于整个集合后面添加了 + 量词,它找到 所有 这些字符(你好!!!),在达到空格时停止。
在第二个命令(非集合)中,+ 量词仅适用于其前面的 %p 类,因此 Luau 只获取第一个小写字符(你)前面的标点符号序列(!!!)。
与字符类一样,集合可以是自身的“相反”。这通过在集合开头的方括号后紧跟一个 ^ 字符来完成。例如,"[%p%s]+" 表示标点符号和空格,而 "[^%p%s]+" 表示 除了 标点符号和空格以外的所有字符。
集合还支持 范围,让您在起始和结束字符之间找到一个完整的匹配。这是一个高级特性,详细信息请参见 Lua 5.1 手册。
字符串捕获
字符串 捕获 是模式中的子模式。这些被括号 () 包围,用于获取(捕获)匹配的子字符串并将它们保存到变量中。例如,以下模式包含两个捕获,(%a+) 和 (%d+),在成功匹配时返回两个子字符串。
local pattern = "(%a+)%s?=%s?(%d+)"local key1, val1 = string.match("二十一个 = 21", pattern)print(key1, val1) --> 二十一个 21local key2, val2 = string.match("两千= 2000", pattern)print(key2, val2) --> 两千 2000local key3, val3 = string.match("一百万=1000000", pattern)print(key3, val3) --> 一百万 1000000
跟随两个 %s 类的 ? 量词是一种安全的添加,因为它使 = 前后的空格变得可选。这意味着如果等号周围缺少一个(或两个)空格,则匹配仍然成功。
在 string.gsub() 函数中,您可以在替换字符串中使用 %1、%2、%3 等,最多到 %9。尽管 Luau 支持最多 32 个捕获组而不会引发错误,但您只能使用此语法引用前九个捕获。
local str = "爱玩 Roblox"local pattern = "(%w+)(%d+)(%w+)%s+(%w+)"local replacement = "我 %1 %2 %3 %4!"local result = string.gsub(str, pattern, replacement)print(result) --> 我 爱 2 玩 Roblox!
您还可以嵌套字符串捕获:
local places = "云之国是天堂,森林王国是宁静的"local pattern = "(云%s(%a+%s王国)[%w%s]+)"for description, kingdom in string.gmatch(places, pattern) doprint(description)print(kingdom)end--> 云之国是天堂--> 云国--> 森林王国是宁静的--> 森林王国
该模式搜索的工作原理如下:
string.gmatch() 迭代器在外部括号定义的整个 "description" 模式上查找匹配。这在第一个逗号处停止并捕获以下内容:
| # | 模式 | 捕获 |
|---|---|---|
| 1 | (云%s(%a+%s王国)[%w%s]+) | 云之国是天堂 |
使用其成功的第一次捕获,迭代器然后查找与内对括号定义的“王国”模式的匹配。该嵌套模式简单地捕获以下内容:
| # | 模式 | 捕获 |
|---|---|---|
| 2 | (%a+%s王国) | 云国 |
然后,迭代器向后退出并继续搜索完整字符串,捕获以下内容:
| # | 模式 | 捕获 |
|---|---|---|
| 3 | (云%s(%a+%s王国)[%w%s]+) | 森林王国是宁静的 |
| 4 | (%a+%s王国) | 森林王国 |
除此之外,捕获还有一个特殊情况,即 空捕获(())。如果捕获为空,则会捕获字符串中的位置:
local match1 = "捕获在哪里发生?谁知道!"local match2 = "这个字符串比第一个长。捕获在哪里发生?谁知道?!"local pattern = "()捕获在哪里发生?谁知道!()"local start1, finish1 = string.match(match1, pattern)print(start1, finish1) --> 1 42local start2, finish2 = string.match(match2, pattern)print(start2, finish2) --> 43 84
这些特殊捕获可以像普通捕获一样嵌套:
local places = "云之国是天堂,森林王国是宁静的。"local pattern = "云 (%a+()) 王国 是 %a+"for kingdom, position in string.gmatch(places, pattern) doprint(kingdom, position)end--> 云国 10--> 森林 42
返回值是异常的,因为它们是 数字 而不是字符串:
local match = "这是一个例子"local pattern = "这是一个 ()例子"local position = string.match(match, pattern)print(typeof(position)) --> number