字符串是不可变的

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                没有
(?:...)           没有(所有括号都是捕获)

复杂场景用 LPeglrexlib(绑定 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)

→ 下一篇 控制流