字符串是不可变的
local s = "hello"
-- s[1] = "H" -- 报错:字符串不支持索引赋值
s = "Hello" -- ✅ 重新赋值
修改 = 造新字符串。
取字符
Lua 没原生字符索引。用 string.sub:
local s = "hello"
print(string.sub(s, 1, 1)) -- "h"(索引从 1 开始!)
print(string.sub(s, 2, 4)) -- "ell"
print(string.sub(s, -3)) -- "llo"(负数从末尾)
或冒号方法(语法糖,等价于上面):
print(s:sub(1, 1)) -- "h"
print(s:upper()) -- "HELLO"
print(s:len()) -- 5(等于 #s)
print(s:rep(3)) -- "hellohellohello"
: 是 Lua 的 OOP 调用——s:sub(1, 1) 等价 string.sub(s, 1, 1)。
长字符串
local sql = [[
SELECT *
FROM users
WHERE id = 1
]]
不需要 \n 转义、单双引号都自由。
含 ]] 时用长括号 [==[ ... ]==](= 数任意多,配对即可)。
string.format
像 C 的 printf:
print(string.format("名字 %s, 年龄 %d", "Alice", 30))
print(string.format("%.2f", 3.14159)) -- 3.14
print(string.format("%05d", 42)) -- 00042
print(string.format("%x", 255)) -- ff
print(string.format("%q", 'He said "hi"')) -- "He said \"hi\""
%s 字符串、%d 整数、%f 浮点、%x 十六进制、%q 转义引号。
模式(Pattern)——Lua 的"小正则"
Lua 不用 PCRE,自带一套精简模式语法:
local s = "hello, 2026-05-11 world"
print(s:find("world")) --> 17 21(起止索引)
print(s:match("%d+%-%d+%-%d+")) --> "2026-05-11"
print(s:gsub("%d", "*")) --> "hello, ****-**-** world" 8
for word in s:gmatch("%a+") do -- 找所有字母词
print(word)
end
-- hello / world
字符类
| 匹配 | |
|---|---|
%a |
字母 |
%d |
数字 |
%s |
空白 |
%w |
字母数字 |
%p |
标点 |
%A / %D / ... |
上面的取反(大写) |
. |
任意字符 |
量词
| 含义 | |
|---|---|
* |
0 个或多个(贪婪) |
+ |
1 个或多个(贪婪) |
- |
0 个或多个(非贪婪,不是减号!) |
? |
0 个或 1 个 |
捕获
local date = "2026-05-11"
local y, m, d = date:match("(%d+)-(%d+)-(%d+)")
print(y, m, d) -- 2026 05 11
括号 = 捕获组。
Lua 模式 vs 正则
PCRE Lua
[0-9]+ %d+
[a-zA-Z] %a
\d %d
*? (lazy) - (注意是减号符号)
\b 没有
(?:...) 没有(所有括号都是捕获)
复杂场景用 LPeg 或 lrexlib(绑定 PCRE)。
转换
tonumber("123") --> 123
tonumber("abc") --> nil(失败返回 nil,不抛错)
tonumber("ff", 16) --> 255
tostring(123) --> "123"
tostring(nil) --> "nil"
tostring({}) --> "table: 0x..."
常用 string 函数
string.upper(s) -- "HELLO"
string.lower(s) -- "hello"
string.reverse(s) -- "olleh"
string.byte("A") -- 65
string.char(65) -- "A"
table.concat({"a", "b", "c"}, "-") -- "a-b-c"
注意:拼接大量字符串别用 ..——慢。用 table.concat:
local parts = {}
for i = 1, 1000 do parts[#parts + 1] = tostring(i) end
local s = table.concat(parts)
→ 下一篇 控制流