Lua 教程 - 第六章:字符串进阶
第六章:字符串进阶
Lua 的字符串处理能力非常强大,尤其是它的模式匹配(Pattern Matching)机制。虽然它不像 Perl 或 Python 的正则表达式(Regex)那样功能全面,但 Lua 的模式匹配设计得更加轻量、高效,足以应对绝大多数日常需求。
本章将详细讲解 Lua 的模式匹配语法、常用的字符串函数以及如何进行高效的文本处理。
6.1 模式匹配基础
Lua 的模式匹配使用一些特殊字符来描述字符串的结构。
字符类 (Character Classes)
字符类用于匹配一组字符中的任意一个。
-
.: 任意字符 -
%a: 字母 -
%c: 控制字符 -
%d: 数字 -
%l: 小写字母 -
%p: 标点符号 -
%s: 空白字符 -
%u: 大写字母 -
%w: 字母和数字 -
%x: 十六进制数字 -
%z: 内部表示为 0 的字符
注意:大写形式表示补集。例如 %D 表示非数字,%S 表示非空白字符。
自定义字符类
使用 [] 可以自定义字符类。
-
[abc]: 匹配 a, b, 或 c -
[0-9]: 匹配 0 到 9 的数字 (等同于%d) -
[^abc]: 匹配除了 a, b, c 以外的字符
修饰符 (Modifiers)
修饰符用于指定字符重复出现的次数。
-
*: 重复 0 次或多次(最长匹配,贪婪) -
+: 重复 1 次或多次(最长匹配,贪婪) -
-: 重复 0 次或多次(最短匹配,非贪婪) -
?: 重复 0 次或 1 次
锚点 (Anchors)
-
^: 匹配字符串开头 -
$: 匹配字符串结尾
捕获 (Captures)
使用圆括号 () 可以将匹配到的部分捕获起来,用于后续使用。
6.2 常用字符串函数
string.find (查找)
查找模式在字符串中首次出现的位置。返回起始索引和结束索引。
s = "Hello Lua User"
i, j = string.find(s, "Lua")
print(i, j) -- 7 9
print(string.sub(s, i, j)) -- Lua
string.match (匹配)
返回匹配到的子串。如果使用了捕获,则返回所有捕获的值。
date = "Today is 15/02/2026"
d, m, y = string.match(date, "(%d+)/(%d+)/(%d+)")
print(d, m, y) -- 15 02 2026
string.gsub (全局替换)
gsub (Global SUBstitution) 用于将所有匹配到的模式替换为指定字符串。
s = "Lua is cute"
new_s, count = string.gsub(s, "cute", "great")
print(new_s) -- Lua is great
print(count) -- 1 (替换次数)
-- 使用捕获进行重排
s = "Key = Value"
print(string.gsub(s, "(%w+)%s*=%s*(%w+)", "%2 = %1"))
-- Value = Key
gsub 的第三个参数不仅可以是字符串,还可以是表或函数:
-
表: 用匹配到的内容作为键去查表,用查到的值替换。
-
函数: 用匹配到的内容作为参数调用函数,用返回值替换。
t = {name="lua", version="5.4"}
s = "$name-$version.tar.gz"
print(string.gsub(s, "$(%w+)", t))
-- lua-5.4.tar.gz
string.gmatch (迭代匹配)
返回一个迭代器,每次调用返回下一个匹配到的子串。通常配合 for 循环使用。
s = "hello world from lua"
for w in string.gmatch(s, "%a+") do
print(w)
end
-- 输出:
-- hello
-- world
-- from
-- lua
6.3 进阶技巧
贪婪与非贪婪匹配
默认情况下,* 和 + 是贪婪的,它们会尽可能多地匹配字符。而 - 是非贪婪的,它会尽可能少地匹配。
s = 'a "one" and "two"'
print(string.match(s, '".*"')) -- "one" and "two" (贪婪)
print(string.match(s, '".-"')) -- "one" (非贪婪)
模式转义
如果要匹配特殊字符(如 ., (, ), %, +, -, *, ?, [, ], ^, $, \0),需要在前面加 % 进行转义。
例如匹配百分号 %,需要写成 %%。
边界匹配
%bxy 用于匹配以字符 x 开始并以字符 y 结束的平衡字符串。这对于匹配括号非常有用。
s = "a (enclosed (in) parentheses) line"
print(string.match(s, "%b()")) -- (enclosed (in) parentheses)
练习题
-
编写一个函数
trim(s),去除字符串首尾的空白字符。 -
给定一个 URL 字符串(如
"http://www.lua.org/manual/5.4/manual.html"),使用模式匹配提取协议(http)、域名(www.lua.org)和路径(/manual/5.4/manual.html)。 -
将字符串
"the quick brown fox"中的每个单词首字母大写。 -
解析 CSV 格式的行:
"Apple, Banana, \"Grape, Green\", Orange",注意处理引号内的逗号。
下一章预告:我们将学习 Lua 的 I/O 库,掌握如何读取文件、写入文件以及处理标准输入输出流。

