速查

最常用的几个:

string.upper(s)          -- 大写
string.lower(s)          -- 小写
string.len(s)            -- 长度(= #s)
string.sub(s, i, j)      -- 子串
string.rep(s, n)         -- 重复 n 次
string.reverse(s)        -- 反转
string.byte(s, i)        -- 第 i 个字符的 ASCII
string.char(...)         -- ASCII → 字符
string.format(fmt, ...)  -- printf 风格

冒号语法等价:s:upper() = string.upper(s)

find / match / gmatch / gsub

4 个模式匹配函数——区别细微。

find

local s = "Hello, World"
print(s:find("World"))           -- 8  12
print(s:find("World", 1, true))  -- 8  12(plain 模式,不解释为模式)
print(s:find("nope"))            -- nil

返回 起始, 结束(plain=true 时按字面匹配)。

match

print(("abc123"):match("%d+"))        -- "123"
print(("user@email.com"):match("(.+)@(.+)"))  -- "user"  "email.com"

返回捕获组;如果无捕获,返回整个匹配。

gmatch

for word in ("hello world foo"):gmatch("%a+") do
    print(word)
end
-- hello / world / foo

迭代器风格——所有匹配。

gsub

print(("hello"):gsub("l", "L"))           -- "heLLo"  2
print(("hello"):gsub("l", "L", 1))        -- "heLLo" 1  限制次数

-- 用函数替换
print(("abc"):gsub("%a", function(c) return c:upper() end))
-- "ABC"  3

-- 用表查
local subs = {a = "1", b = "2"}
print(("abc"):gsub(".", subs))
-- "12c"  3   (c 不在表里,保持原样)

返回 新字符串, 替换次数

模式语法回顾

详见 第 04 篇 末尾——这里补充进阶。

锚定

"^abc"       -- 字符串开头
"abc$"       -- 字符串结尾
"^abc$"      -- 完全匹配

字符集

"[abc]"      -- a 或 b 或 c
"[^abc]"     -- 除 a/b/c 之外
"[a-z]"      -- a 到 z
"[a-zA-Z0-9_]"

转义

"%."         -- 字面的 .(特殊字符前加 %)
"%%"         -- 字面的 %

特殊字符列表:( ) . % + - * ? [ ] ^ $

反向引用

print(("hello"):match("(%a)%1"))    -- "l"(重复字符)

%1 引用第 1 个捕获——能匹配"前后相同"的模式。

字符串拼接慢——用 table.concat

-- 慢:O(n²)
local s = ""
for i = 1, 10000 do s = s .. i end

-- 快:O(n)
local parts = {}
for i = 1, 10000 do parts[#parts + 1] = tostring(i) end
local s = table.concat(parts)

每次 .. 都造新字符串。大循环里永远用 table.concat

性能:不要在热路径反复创建模式

-- 慢
for line in io.lines("x") do
    local n = line:match("(%d+)")
end

-- 快(5.1 / LuaJIT 没差,5.3+ 内部缓存最近的模式)

实际上现代 Lua 已缓存——这是 LuaJIT 时代的老优化。但别在内层循环写超复杂模式——还是建议预处理。

UTF-8

Lua 5.3+ 自带 utf8 库:

local s = "你好"
print(#s)                  -- 6(字节数)
print(utf8.len(s))         -- 2(字符数)
print(utf8.char(0x4F60))   -- "你"
print(utf8.codepoint(s, 1, -1))  -- 20320  22909

for i, c in utf8.codes(s) do
    print(i, utf8.char(c))
end

5.1 / LuaJIT 没——需要 luautf8 库。

→ 下一篇 math / io / os 库