目录
注:本系列为《Lua程序设计-第4版》 的读书笔记,其中的见解有不完善的地方,可以在评论区指出,原版请看图书
5.1.2 魔法字符:具有特殊含义的字符( 注意,仅仅是使用魔法字符的字符时, 需要用%转义)
5.1.5 以补字符^ 开头的模式表示从目标字符串的开头开始匹配,以$结尾的模式表示匹配到字符串结尾。可以同时使用这两标记来限制匹配查找和锚定
5.1.6 模式'%b' 匹配成对的字符串,它的写法是'%bxy', 其中x 和 y 是任意两个不同的字符,x作为起始字符而y作为结束字符
注:本系列为《Lua程序设计-第4版》 的读书笔记,其中的见解有不完善的地方,可以在评论区指出,原版请看图书
一. 函数string.find
用于在指定的目标字符串中搜索指定的模式。最简单的模式就是一个单词,它只会匹配到这个单词本身。函数string.find找到一个模式后,会返回两个值:匹配到模式开始位置的索引和结束位置的索引,如果没有找到任何匹配,则返回nil
s = "hello world"
i, j = string.find(s, "hello")
print(i, j) --> 1 5
print(string.sub(s, i, j)) --> hello
print(sting.find(s, "world")) --> 7 11
i, j = string.find(s, "l")
print(i, j) --> 3 3
print(string.find(s, "lll")) --> nil
匹配成功后,可以以函数 find 返回的结果为参数调用函数string.sub 来获取目标字符串中匹配相应模式的字串。
函数string.find 具有两个可选参数
第3个参数是一个索引,用于说明从目标字符串的哪个位置开始搜索。
第4个参数是一个布尔值,用于说明是否进行简单搜索。简单搜索即忽略模式而在目标字符串中进行单纯的”查找字符串“的动作。
string.find("a[word]", "[") --> stdin:1:malformed pattern (missing ']')
string.find("a [word]", "[", 1, true) -- 3 3
由于 '[' 在模式中具有特殊含义,因此第1个函数调用会报错。在第2个函数调用中,函数只是把 '['当作简单字符串。
二 函数 string.match
由于函数string.match 也用于在一个字符串中搜索模式,因此它与函数string.find 非常相似。不过,函数string.match 返回的是目标字符串中与模式相匹配的那部分字符串,而非该模式所在位置:
print(sting.match("hello world", "hello")) -- hello
三. 函数 string.gsub()
函数 string.gsub 有3个必选参数:目标字符串、模式和替换字符串
s = string.gsub("Lua is cute", "cute", "great")
print(s) --> Lua is great
s = string.gsub("all lii", "l", "x")
print(s)
s = string.gsub("Lua is great", "Sol", "Sun")
print(s) --> Lua is great
该函数还有一个 可选的第4个参数,用于限制替换的次数:
s = string.gsub("all lii", "l", "x", 1)
print(s) --> axl lii
s , n = string.gsub("all lii", "l", "x", 2)
print(s) --> axx lii
print(n) --> 2
函数 sting.gsub 还会返回第2个结果,即发生替换的次数。
四. 函数 string.gmatch
函数 string.gmatch 返回一个函数,通过返回的函数可以遍历一个字符串所有出现的指定模式。例如,以下示例可以找到指定字符串s中出现的所有单词:
s = "some string"
words = {}
for w in string.gmath(s, "%a+") do
words[#words + 1] = w
end
五. 模式
大多数的模式匹配库都使用反斜杆作为转义符,但对Lua解析器来说,模式仅仅是字符串,模式和其他字符串一样遵循相同的规则,并不会被特殊对待;只有模式匹配函数才会对它们当做模式对待。
由于反斜杠是Lua语言的转义符,所以应该避免将它传递到任何函数。
Lua语言中的模式使用百分号作为转义符。总体上,所有被转义的字母都具有某些特殊含义(例:'%a'匹配所有字母); 而所有被转义的非字母都代表其本身('%.' 匹配一个点)
5.1 字符匹配模式
含义:模式中能够与一个特定集合中的任意字符相匹配的一项。例如,分类%d匹配的是任意数字。因此,可以使用模式'%d%d/%d%d/%d%d%d%d'来匹配dd/mm/yyyy格式的日期:
s = "Deadline is 30/05/1999, firm"
date = "%d%d/%d%d/%d%d%d%d"
print(string.match(s, date)) --> 30/05/1999
5.1.1 预置的字符分类
预置的字符分类及含义 | |
预置的字符 | 含义 |
. | 任意字符 |
%a | 字母 |
%c | 控制字符 |
%d | 数字 |
%g | 除空格外可打印的字符 |
%l | 小写字符 |
%p | 标点符号 |
%s | 空白字符 |
%u | 大写字母 |
%w | 字母和数字 |
%x | 十六进制数字 |
这些分类的大写形式表示类的补集。例如 '%A'代表任意非字母的字符:
print((string.gsub("hello, up-down!", "%A", ".")))
--> hello..up..down.
5.1.2 魔法字符:具有特殊含义的字符( 注意,仅仅是使用魔法字符的字符时, 需要用%转义)
(
)
.
%
+
-
*
?
[
]
^
$
百分号%同样可以对于这些魔法字符的转义。因此,'%?'匹配一个问号,'%%'匹配一个百分号,百分号不止可以对魔法字符转义,还可以用于其他所有字母和数字外的字符
5.1.3 使用字符集创建自定义字符分类
只需要在方括号内将单个字符和字符分类组合起来。例如,字符集 '[%w_]'匹配所有以下划线结尾的字母和数字, '[01]'匹配二进制数字,'[%[%]]'匹配方括号。
还可以在字符集中包含一段字符范围,用法:写出字符范围的第一个字符和最后一个字符并用横线将它们连接在一起。
例如:'[0-9]'相对于 '%d', '%x' 相当于 '[0-9a-fA-F]'
字符集前加一个补字符^就可以得到这个字符集对应的补集: 模式 '[^0-7]'查找所有八进制数字之外的字符, 模式'[^\n]'匹配换行符之外的其他字符
如果方括号内是预置的字符分类(5.1.1),此时求补集可以 直接用大写形式表示。例,%S 和 '[^%s]' 是一样的,都表示空格之外的字符,但是 %S更简洁
5.1.4 修饰符
修饰符 | 含义 |
+ | 重复一次或多次 |
* | 重复零次或多次 |
- | 重复零次或多次(最小匹配) |
? | 可选(出现零次或一次) |
修饰符+:
匹配原始字符串分类中的一个或多个字符·,它总是获取模式相匹配的最长序列:例,模式'%a+' 表示一个或多个字母
print(string.gsub("one, and two;and three", "%a+", "word")))
--> word, word word;word word
修饰符*:
类似修饰符+,但是接受出现零次的情况。该修饰符的典型用法是在模式的部分之间匹配可选的空格
例如:匹配像() 或者 ( )这样的空括号对,可以使用模式 '%(%s*%)',其中的'%s*'匹配零个或多个空格(括号属于魔法字符,具有特殊含义,所以必须转义)
修饰符 -
与 修饰符 * 类似,不过只会匹配最短序列
修式符 ?
用于匹配一个可选字符。
例如:我们想在一段文本中寻找一段整数,而这个整数可能包括一个可选的符号,那么可以用模式'[+-]?%d+'
5.1.5 以补字符^ 开头的模式表示从目标字符串的开头开始匹配,以$结尾的模式表示匹配到字符串结尾。可以同时使用这两标记来限制匹配查找和锚定
例如:检查字符串s是否以数字开头
if string.find(s, "^%d") then ...
例如: 检查字符串是否为一个没有多余前缀和后缀字符的整数
if string.find(s, "^[+-]?%d$") then ...
注意:^ 和 & 字符只有位于模式开头或结尾时才有特殊含义
5.1.6 模式'%b' 匹配成对的字符串,它的写法是'%bxy', 其中x 和 y 是任意两个不同的字符,x作为起始字符而y作为结束字符
例如:模式'%b()' 匹配以左括号开始,右括号结束的字符
s = "a(enclosed(in)) line"
print(string.gsub(s,"%b()", "")) --> a line