第 9 章 字符串与模式匹配
第 9 章 字符串与模式匹配
字符串处理是脚本语言最常见的任务。Lua 的 string 库提供查找、替换、格式化与模式匹配能力,语义与正则表达式相似但不完全相同。
常用字符串函数
local text = " Lua 5.4 "
print(#text)
print(text:lower())
print(text:upper())
print(text:rep(2))
print(text:sub(3, 8))
print(text:gsub(" ", "_"))
sub 使用闭区间索引,负数表示从末尾倒数。gsub 默认替换全部匹配,并返回替换后的字符串和替换次数。
local result, count = ("a-b-c"):gsub("%-", "/")
print(result, count) -- a/b/c 2
Lua 模式语法
Lua 模式不是完整的正则表达式。常用规则:
| 模式 | 含义 |
|---|---|
. |
任意字符 |
%a |
字母 |
%d |
数字 |
%s |
空白字符 |
%w |
字母或数字 |
%p |
标点 |
+ |
一次或多次 |
* |
零次或多次 |
- |
最短匹配 |
? |
零次或一次 |
^ |
字符串开头 |
$ |
字符串结尾 |
() |
捕获组 |
转义特殊字符使用 %:
print(("a.b.c"):find("%."))
print(("100%"):match("%d+%%"))
查找、捕获与替换
find
local startIndex, endIndex, name = ("user=ada"):find("(%w+)=(%w+)")
print(startIndex, endIndex)
match
local key, value = ("timeout=30"):match("^(%w+)=(%d+)$")
print(key, value)
gmatch
gmatch 返回迭代器,用于逐项提取:
for word in ("Lua is lightweight"):gmatch("%a+") do
print(word)
end
gsub
local text = "name: Ada, age: 30"
local result = text:gsub("(%w+):", "%1 =")
print(result) -- name = Ada, age = 30
替换函数可以基于捕获值动态生成内容:
local result = ("2 + 3 = 5"):gsub("%d+", function(number)
return tostring(tonumber(number) * 2)
end)
格式化与文本处理
string.format 适合生成固定格式文本:
local name = "Lua"
local version = 5.4
local message = string.format("%s %.1f", name, version)
print(message)
常用占位符:
-
%s:字符串 -
%d:十进制整数 -
%x:十六进制整数 -
%f:浮点数 -
%q:可安全转义为 Lua 字面量的字符串 -
%%:百分号
不要用字符串拼接生成结构化数据。JSON、配置和日志都有专门的编码、校验与转义规则。
编写一个简单解析器
下面解析 key=value 格式的配置文本:
local function parseConfig(text)
local config = {}
local lineNumber = 0
for line in text:gmatch("[^\r\n]+") do
lineNumber = lineNumber + 1
line = line:match("^%s*(.-)%s*$")
if line ~= "" and not line:match("^#") then
local key, value = line:match("^([%w_%-%.]+)%s*=%s*(.+)$")
if not key then
error(string.format("第 %d 行格式错误: %s", lineNumber, line))
end
config[key] = value
end
end
return config
end
生产代码中还应限制输入大小、给错误附带行号,并明确重复键的处理策略。