Chapter 21_2 模式匹配函数

时间:2023-11-23 09:57:56

  基础函数比较简单,就是几个普通的函数string.byte、string.char、string.rep、string.sub、string.format还有大小写转换函数upper和lower。

  接下来介绍最强大的函数,find、match、gsub、和gmatch,它们都是基于“模式(pattern)”的。

  不同于其他脚本语言,Lua既没有用POSIX,也没有使用Perl正则表达式来进行模式匹配。主要因为考虑到Lua的大小。

  POSIX需要超过4000多行代码,相当于所有Lua标准库加在一起的大小。

  相比之下,Lua采用的不到500行。虽然功能上达不到完整的POSIX实现。但是也是一个强大的工具,甚至有些特性比POSIX更为方便。

  • find 函数

  该函数用于在给定的目标字符串中搜索一个模式。最简单的就是一个单词,它只会匹配与自己完全相同的拷贝。

  例如:模式“hello” 会搜索目标中的子串“hello”。找到后,返回两个值:一个起始索引、一个结尾索引。没有找到就返回nil。

 s = "hello world"
i , j = string.find(s,"hello")
print(i , j ) --> 1 5
print(string.sub(s , i , j ))     --> hello --用简单函数里的sub 截取i 到 j 的字符串,这样的简单模式,取出的就是模式自身
print(string.find(s , "world"))  --> 7 11
i , j = stirng.find(s , "l")
print(i , j ) --> 3 3 -- 起始为索引3,结尾也为索引3
print(string.find(s , "lll"))    --> nil

  find函数还有一个可选的第三个参数,它是一个索引,告诉函数应从目标字符串的哪个位置开始搜索。

  当处理所有与给定模式相匹配的部分时,这个参数很有用。可以重复搜索新的匹配,且每次搜索都从上一次找到的位置开始。

  下面的例子用字符串中所有换行符的位置创建了一个table:

local t = {} --存储索引的table
local i =
while true do
i = string.find( s , "\n" , i + ) --找下一行
if i == nil then break end
t[#t + ] = i
end
  • match函数

  该函数与find非常相似,也是用在一个字符串中搜索一种模式。

  不同之处在于,match返回的是目标字符中与模式匹配的那部分子串,而非所在位置。

print(string.match("hello world","hello"))    -->hello

  像这样固定的模式,用这个函数就没有什么意义了。

  当使用变量模式时,特性就显现出来了:

date = "Today is 22/9/2016"
d = string.match(date , "%d+/%d+/%d+") -- + 符号表示匹配一或多个该类的字符
print(d)                --> 22/9/2016
  • gsub函数

  它有3个参数:目标字符串、模式、替换字符串。

  将目标字符串中所有出现模式的地方替换为替换字符串。

s = string.gsub("Lua is cute", "cute", "great")
print(s) --> Lua is great
s = string.gsub("all lii" , "l" , "x")
print(s) --> axx xii
s = string.gsub("Lua is great" , "Sol" , "Sun") --没有找到,返回false或nil 时不作替换(保留匹配前的原始串)
print(s) --> Lua is great

  它还有第四个可选参数,可以限制替换的次数:

s = string.gsub("all lii" , "l" ,"x",  ) --替换1次
print(s) --> axl lii
s = string.gsub("all lii " , "l" , ) --替换2次
print(s) --> axx lii

  它还有第二个结果,即实际替换的次数。例如,以下代码就是一种统计字符串中空格数量的简单方法:

count = select(,string.gsub(str , " "," "))  --select函数,返回第2个之后的部分

  简单明了的方法:

s = "he ll o wo rld"
a,count = string.gsub(s," " ," ")
print(a , count ) -->he ll o wo rld 4
  • gmatch函数

  返回一个函数,通过这个返回的函数可以遍历到一个字符串中所有出现指定模式的地方,下面代码找出了给定字符串s中所有的单词:

words = {}
for w in string.gmatch(s , "%a+") do -- %a+ 表示一个或多个任意字母,也就是单词。
words[#words + ] = w
end

  通过gmatch和gsub可以模拟出Lua中的require在寻找模块时所用的搜索策略:

function search(modname , path)
modname = string.gsub(modname , "%.","/") --用目录分隔符"/"替换所有的“.”
for c in string.gmatch(path,"[^;]+") do -- 不包括“;”的最长子串
local fname = string.gsub(c,"?",modname) --对于每个子串中的“?”,都用模块名曲替换,以此获得最终的文件名。
local f = io.open(fname)
if f then
f:close()
return fname
end
end
return nil --not found
end

以上内容来自:《Lua程序设计第二版》和《Programming in Lua  third edition 》