7.2 字符串的常用操作 Lua 字符串常用操作详解 1. 字符串基础 在 Lua 中,字符串是不可变的值序列,可以包含字母、数字、符号等字符。Lua 字符串可以使用三种方式表示: 单引号 : 单引号字符串中,除了单引号自身需要转义 外,其他字符都按字面意思解释。 双引号 : 双引号字符串中,除了双引号自身需要转义 外,还可以使用转义序列,如 (换行), (制表符), (反斜杠) 等。 长括号 或 : 长括号字符串可以跨越多行,并且内部的转义序列会被忽略。这种方式特别适合定义多行文本或包含大量特殊字符的字符串。 代码示例: 2. 字符串长度 使用长度操作符 可以获取字符串的长度(字节数)。 代码示例: 3. 字符串连接 Lua 中使用连接操作符 (两个点) 来连接两个或多个字符串。
1. 字符串基础
在 Lua 中,字符串是不可变的值序列,可以包含字母、数字、符号等字符。Lua 字符串可以使用三种方式表示:
单引号 '...': 单引号字符串中,除了单引号自身需要转义 \' 外,其他字符都按字面意思解释。
双引号 "...": 双引号字符串中,除了双引号自身需要转义 \" 外,还可以使用转义序列,如 \n (换行), \t (制表符), \\ (反斜杠) 等。
长括号 [[...]] 或 [=[...]=]: 长括号字符串可以跨越多行,并且内部的转义序列会被忽略。这种方式特别适合定义多行文本或包含大量特殊字符的字符串。
代码示例:
-- 单引号字符串 local str1 = 'Hello, Lua!' print(str1) -- 输出: Hello, Lua! -- 双引号字符串,包含转义字符 local str2 = "This is a string with a newline: \nAnd a tab: \t." print(str2) -- 输出: -- This is a string with a newline: -- And a tab: . -- 长括号字符串,多行文本 local str3 = [[ This is a multi-line string. ]] print(str3) -- 输出: -- This is a -- multi-line -- string. -- 长括号字符串,包含特殊字符,无需转义 local str4 = [=[ This string contains symbols like ' " \ and [[ ]]. ]=] print(str4) -- 输出: -- This string contains symbols like ' " \ and [[ ]].
2. 字符串长度
使用长度操作符 # 可以获取字符串的长度(字节数)。
代码示例:
local str = "Lua String" local length = #str print("字符串长度:", length) -- 输出: 字符串长度: 10
3. 字符串连接
Lua 中使用连接操作符 .. (两个点) 来连接两个或多个字符串。
代码示例:
local str1 = "Hello" local str2 = "World" local combinedStr = str1 .. ", " .. str2 .. "!" print(combinedStr) -- 输出: Hello, World!
4. 字符串格式化 string.format()
string.format() 函数允许你根据格式化字符串创建新的字符串,类似于 C 语言的 sprintf 函数。它提供了丰富的格式化选项,可以用于控制数字、字符串等的输出格式。
语法: string.format(formatstring, ...)
formatstring: 格式化字符串,包含格式化占位符。
...: 要格式化的参数,与占位符一一对应。
常用格式化占位符:
| 占位符 | 描述 | 示例 |
|---|---|---|
%c |
接受一个数字并将其作为 ASCII 字符输出 | string.format("%c", 65) -> "A" |
%d 或 %i |
接受一个数字并将其格式化为十进制整数 | string.format("%d", 123) -> "123" |
%e 或 %E |
接受一个数字并将其格式化为科学计数法 | string.format("%e", 1234.5) -> "1.234500e+03" |
%f 或 %F |
接受一个数字并将其格式化为浮点数 | string.format("%.2f", 123.456) -> "123.46" |
%g 或 %G |
根据数值大小自动选择 %e 或 %f 格式 |
string.format("%g", 1234.5) -> "1234.5" |
%o |
接受一个数字并将其格式化为八进制整数 | string.format("%o", 8) -> "10" |
%q |
接受一个字符串并将其格式化为适合 Lua 语法的字符串字面量 | string.format("%q", "Hello\nWorld") -> ""Hello\nWorld"" |
%s |
接受一个字符串并按原样输出 | string.format("%s", "Lua") -> "Lua" |
%u |
接受一个数字并将其格式化为无符号十进制整数 | string.format("%u", 123) -> "123" |
%x 或 %X |
接受一个数字并将其格式化为十六进制整数 | string.format("%x", 255) -> "ff" |
%% |
输出百分号 % |
string.format("%%") -> "%" |
修饰符:
可以在占位符中使用修饰符来进一步控制格式:
宽度修饰符: 在 % 后面和格式化字符之间可以指定宽度。例如 %10d 表示输出宽度为 10 的十进制整数,不足宽度时用空格填充(默认右对齐)。可以使用 %-10d 实现左对齐。
精度修饰符: 对于浮点数格式化,可以使用 %.<精度>f 来指定小数点后的位数。例如 %.2f 表示保留两位小数。
代码示例:
local name = "Alice" local age = 30 local score = 95.8 local formattedStr = string.format("Name: %s, Age: %d, Score: %.2f", name, age, score) print(formattedStr) -- 输出: Name: Alice, Age: 30, Score: 95.80 local hexValue = 255 local hexStr = string.format("Hex value of %d is %X", hexValue, hexValue) print(hexStr) -- 输出: Hex value of 255 is FF local paddedNumber = 123 local paddedStr = string.format("Padded number: %5d", paddedNumber) print(paddedStr) -- 输出: Padded number: 123 (右对齐) local leftPaddedStr = string.format("Left padded number: %-5d", paddedNumber) print(leftPaddedStr) -- 输出: Left padded number: 123 (左对齐)
5. 字符串查找与匹配
Lua 提供了几个函数用于在字符串中查找和匹配子串:
string.find(): 在字符串中查找指定模式的第一个匹配项。语法: string.find(str, pattern, init, plain)
str: 要搜索的字符串。
pattern: 要查找的模式字符串。Lua 的模式匹配系统与正则表达式有所不同,更轻量级,但也足以满足常见的需求。
init (可选): 开始搜索的位置,默认为 1。
plain (可选, 布尔值): 如果为 true,则禁用模式匹配,将 pattern 视为普通字符串进行查找。默认为 false (启用模式匹配)。
返回值:
如果找到匹配项,返回匹配项的起始和结束索引。
如果未找到匹配项,返回 nil。
Lua 模式匹配字符:
| 字符 | 描述 |
|---|---|
. |
匹配任何字符 |
%a |
匹配任何字母 |
%c |
匹配任何控制字符 (control-character) |
%d |
匹配任何数字 |
%l |
匹配任何小写字母 |
%p |
匹配任何标点符号 |
%s |
匹配任何空白字符 (空格、制表符、换行符等) |
%u |
匹配任何大写字母 |
%w |
匹配任何字母数字字符 (alphanumeric characters) |
%x |
匹配任何十六进制数字 |
%z |
匹配以 0 结尾的字符 |
( ) |
捕获 |
%bxy |
匹配成对的 x 和 y。例如 %b() 匹配成对的括号 |
^ |
在模式的开头使用,表示匹配字符串的开头 |
$ |
在模式的结尾使用,表示匹配字符串的结尾 |
% |
转义字符,用于匹配特殊字符本身。例如 %% 匹配百分号 % |
模式修饰符:
| 修饰符 | 描述 |
|---|---|
+ |
匹配前一个字符类的一个或多个重复 |
* |
匹配前一个字符类的零个或多个重复 |
- |
匹配前一个字符类的零个或多个重复 (最短匹配) |
? |
匹配前一个字符类的零个或一个 |
代码示例:
local str = "Hello Lua World" -- 查找 "Lua" local start, finish = string.find(str, "Lua") if start then print("找到 'Lua',起始索引:", start, "结束索引:", finish) -- 输出: 找到 'Lua',起始索引: 7 结束索引: 9 end -- 查找 "lua" (区分大小写,找不到) local start2, finish2 = string.find(str, "lua") if not start2 then print("未找到 'lua'") -- 输出: 未找到 'lua' end -- 不区分大小写查找 "lua" (可以使用模式匹配) local start3, finish3 = string.find(str, "[Ll][Uu][Aa]") if start3 then print("找到 'lua' (不区分大小写),起始索引:", start3, "结束索引:", finish3) -- 输出: 找到 'lua' (不区分大小写),起始索引: 7 结束索引: 9 end -- 使用 plain=true 进行普通字符串查找 local start4, finish4 = string.find(str, ".", 1, true) -- 查找字面量 "." if start4 then print("找到字面量 '.',起始索引:", start4, "结束索引:", finish4) -- 输出: 找到字面量 '.',起始索引: 1 结束索引: 1 end -- 查找以 "W" 开头的单词 local start5, finish5 = string.find(str, "%sW%w+") -- %s 空白字符, W 字面量 W, %w+ 一个或多个字母数字字符 if start5 then print("找到以 'W' 开头的单词,起始索引:", start5, "结束索引:", finish5) -- 输出: 找到以 'W' 开头的单词,起始索引: 10 结束索引: 14 end
string.match(): 在字符串中查找指定模式的第一个匹配项,并返回捕获到的子串。语法: string.match(str, pattern, init)
str: 要搜索的字符串。
pattern: 模式字符串,可以包含捕获组 ()。
init (可选): 开始搜索的位置,默认为 1。
返回值:
如果找到匹配项,返回捕获到的子串。如果没有捕获组,则返回整个匹配的子串。如果有多个捕获组,则返回多个值。
如果未找到匹配项,返回 nil。
代码示例:
local str = "Name: Alice, Age: 30" -- 提取名字 local name = string.match(str, "Name: (%a+)") -- (%a+) 捕获一个或多个字母 if name then print("提取的名字:", name) -- 输出: 提取的名字: Alice end -- 提取年龄 local age = string.match(str, "Age: (%d+)") -- (%d+) 捕获一个或多个数字 if age then print("提取的年龄:", age) -- 输出: 提取的年龄: 30 end -- 提取名字和年龄 (使用多个捕获组) local name2, age2 = string.match(str, "Name: (%a+), Age: (%d+)") if name2 and age2 then print("提取的名字:", name2, "提取的年龄:", age2) -- 输出: 提取的名字: Alice 提取的年龄: 30 end
string.gmatch(): 返回一个迭代器,用于遍历字符串中所有匹配指定模式的子串。语法: string.gmatch(str, pattern)
str: 要搜索的字符串。
pattern: 模式字符串。
返回值:
nil。代码示例:
local str = "apple, banana, orange, apple" -- 查找所有 "apple" for fruit in string.gmatch(str, "apple") do print("找到 apple:", fruit) end -- 输出: -- 找到 apple: apple -- 找到 apple: apple -- 查找所有单词 for word in string.gmatch(str, "%w+") do -- %w+ 匹配一个或多个字母数字字符 print("单词:", word) end -- 输出: -- 单词: apple -- 单词: banana -- 单词: orange -- 单词: apple
6. 字符串截取 string.sub()
string.sub() 函数用于提取字符串的子串。
语法: string.sub(str, i, j)
str: 要截取的字符串。
i: 子串的起始索引 (包含)。可以是正数(从字符串开头开始计数)或负数(从字符串结尾开始计数,-1 表示最后一个字符)。
j (可选): 子串的结束索引 (包含)。可以是正数或负数。如果省略,则截取到字符串末尾。
代码示例:
local str = "Lua String" -- 截取 "Lua" (索引从 1 开始) local subStr1 = string.sub(str, 1, 3) print("子串 1:", subStr1) -- 输出: 子串 1: Lua -- 截取 "String" local subStr2 = string.sub(str, 5) -- 省略 j,截取到末尾 print("子串 2:", subStr2) -- 输出: 子串 2: String -- 使用负数索引截取最后 6 个字符 "String" local subStr3 = string.sub(str, -6) print("子串 3:", subStr3) -- 输出: 子串 3: String -- 使用负数索引截取 "ing" local subStr4 = string.sub(str, -3, -1) print("子串 4:", subStr4) -- 输出: 子串 4: ing
7. 字符串替换 string.gsub()
string.gsub() 函数用于在字符串中替换匹配模式的子串。
语法: string.gsub(str, pattern, replacement, n)
str: 要进行替换的字符串。
pattern: 要查找的模式字符串。
replacement: 替换字符串。也可以是一个函数,用于动态生成替换字符串。
n (可选): 最多替换的次数。如果省略,则替换所有匹配项。
返回值:
返回替换后的新字符串。
返回替换发生的次数。
代码示例:
local str = "Hello Lua Lua World" -- 将第一个 "Lua" 替换为 "Moon" local newStr1, count1 = string.gsub(str, "Lua", "Moon", 1) print("替换后的字符串 1:", newStr1, "替换次数:", count1) -- 输出: 替换后的字符串 1: Hello Moon Lua World 替换次数: 1 -- 将所有 "Lua" 替换为 "Moon" local newStr2, count2 = string.gsub(str, "Lua", "Moon") -- 省略 n,替换所有 print("替换后的字符串 2:", newStr2, "替换次数:", count2) -- 输出: 替换后的字符串 2: Hello Moon Moon World 替换次数: 2 -- 使用函数作为替换参数,将所有 "Lua" 替换为 "Moon" 并转为大写 local newStr3, count3 = string.gsub(str, "Lua", function(match) return string.upper(match) -- 将匹配到的字符串转为大写 end) print("替换后的字符串 3:", newStr3, "替换次数:", count3) -- 输出: 替换后的字符串 3: Hello LUA LUA World 替换次数: 2 -- 交换 "Hello" 和 "World" 的位置 local str2 = "Hello World" local newStr4, count4 = string.gsub(str2, "(%a+) (%a+)", "%2 %1") -- (%a+) 捕获单词, %2 和 %1 分别表示第二个和第一个捕获组 print("替换后的字符串 4:", newStr4, "替换次数:", count4) -- 输出: 替换后的字符串 4: World Hello 替换次数: 1
8. 大小写转换 string.lower() 和 string.upper()
string.lower(str): 将字符串中的所有大写字母转换为小写字母。
string.upper(str): 将字符串中的所有小写字母转换为大写字母。
代码示例:
local str = "Hello Lua World" local lowerStr = string.lower(str) print("小写字符串:", lowerStr) -- 输出: 小写字符串: hello lua world local upperStr = string.upper(str) print("大写字符串:", upperStr) -- 输出: 大写字符串: HELLO LUA WORLD
9. 字符串反转 string.reverse()
string.reverse(str) 函数将字符串反转。
代码示例:
local str = "Lua" local reversedStr = string.reverse(str) print("反转字符串:", reversedStr) -- 输出: 反转字符串: auL
10. 字符串重复 string.rep()
string.rep(str, n) 函数将字符串 str 重复 n 次。
代码示例:
local str = "Lua" local repeatedStr = string.rep(str, 3) print("重复字符串:", repeatedStr) -- 输出: 重复字符串: LuaLuaLua
11. 字符码转换 string.char() 和 string.byte()
string.char(...): 接受零个或多个整数参数,将每个整数视为 ASCII 字符码,并返回由这些字符组成的字符串。
string.byte(str, i, j): 返回字符串 str 中从索引 i 到 j (包含) 的字符的内部数字代码。如果不指定 i,则默认为 1。如果不指定 j,则默认为 i。
代码示例:
-- string.char() local charStr = string.char(65, 66, 67) -- 65=A, 66=B, 67=C print("字符码转字符串:", charStr) -- 输出: 字符码转字符串: ABC -- string.byte() local byteCode = string.byte("ABC", 2) -- 获取 'B' 的字符码 print("'B' 的字符码:", byteCode) -- 输出: 'B' 的字符码: 66 local byteCodes = string.byte("ABC", 1, 3) -- 获取 "ABC" 所有字符的字符码 print("'ABC' 的字符码:", byteCodes) -- 输出: 'ABC' 的字符码: 65 66 67
12. 字符串比较
Lua 可以直接使用比较运算符 (==, ~=, <, <=, >, >=) 比较字符串。字符串比较是按照字典顺序进行的。
代码示例:
local str1 = "apple" local str2 = "banana" local str3 = "apple" print("str1 == str2:", str1 == str2) -- 输出: str1 == str2: false print("str1 == str3:", str1 == str3) -- 输出: str1 == str3: true print("str1 < str2:", str1 < str2) -- 输出: str1 < str2: true print("str2 > str3:", str2 > str3) -- 输出: str2 > str3: true
13. 字符串与数字转换 tonumber() 和 tostring()
tonumber(str, base): 尝试将字符串 str 转换为数字。如果转换成功,返回数字;否则返回 nil。base 参数是可选的,用于指定数字的进制,默认为十进制。
tostring(v): 将任何类型的值 v 转换为字符串。对于数字,它会将数字转换为字符串表示形式。
代码示例:
-- tonumber() local numStr = "123" local num = tonumber(numStr) if num then print("字符串转数字:", num, type(num)) -- 输出: 字符串转数字: 123 number end local hexStr = "FF" local hexNum = tonumber(hexStr, 16) -- 从十六进制字符串转换 if hexNum then print("十六进制字符串转数字:", hexNum) -- 输出: 十六进制字符串转数字: 255 end local invalidNumStr = "abc" local invalidNum = tonumber(invalidNumStr) if not invalidNum then print("字符串无法转换为数字") -- 输出: 字符串无法转换为数字 end -- tostring() local num2 = 456 local numStr2 = tostring(num2) print("数字转字符串:", numStr2, type(numStr2)) -- 输出: 数字转字符串: 456 string
总结
本文详细介绍了 Lua 语言中常用的字符串操作,包括字符串的创建、长度获取、连接、格式化、查找匹配、截取、替换、大小写转换、反转、重复、字符码转换、比较以及字符串与数字之间的转换。 掌握这些操作是 Lua 编程的基础,能够帮助你有效地处理文本数据,构建更强大的应用程序。 Lua 的字符串操作功能强大且灵活,希望本文能够帮助你更好地理解和运用它们。