在 lua 中的正则简单使用

本来想继续放在同一篇测试博客的 LearnLua - 学习笔记,但是发现单一一篇博客太多 Markdown 内容会卡到爆,所以还是分开来写了


string match pattern - 字符匹配

其实这算是 lua 内置的正则表达式吧,只不过它的转义符为 % 而不是我们其他 C 类语言的 \

可以查看官方文档的简述(正的很简述,如果你以前没使用过正则,就不建议查看官方的简述文档帮助不大,硬是从 lua 的正则来入门的话,我建议你买 lua 的书籍)

官方资料:官方简述文档-string

  • string.gmatch(s, pattern, [, init])
    • s 是需要匹配的正文
    • pattern 是正则表达式
    • init 是可选项,就是在 s 的第几个字符开始匹配,默认为 1
    • @return 返回的是 group 分组 的匹配结果,如果正则表达是没有用分组匹配,那么返回的就是匹配的字符内容
  • string.gsub (s, pattern, repl [, n])
    • s 是需要匹配的正文
    • pattern 是正则表达式
    • repl 设置 repl 就可以将匹配到的字符内容替换为 repl 的内容
    • n

另外正则表达式可以在 vsc 或是 sublime 中很方便的验证匹配性,一般会我选择在 sublime 中输入需要匹配的文本内容,然后 Ctrl + F 或是 Ctrl + H(如果需要替换的话)然后勾上正则开关,就可以输入正则表达式来测试匹配了


string.gmatch - 分组匹配

它返回的是匹配到的字符迭代器函数

官方的例子:

Returns an iterator function that, each time it is called, returns the next captures from pattern (see §6.4.1) over the string s. If pattern specifies no captures, then the whole match is produced in each call. A third, optional numeric argument init specifies where to start the search; its default value is 1 and can be negative.

As an example, the following loop will iterate over all the words from string s, printing one per line:

 s = "hello world from Lua"
 for w in string.gmatch(s, "%a+") do
   print(w)
 end

The next example collects all pairs key=value from the given string into a table:

 t = {}
 s = "from=world, to=Lua"
 for k, v in string.gmatch(s, "(%w+)=(%w+)") do
   t[k] = v
 end

下面是我自己测试的例子

local test_str = "a + b = c;\n1  +   2 =3;100-1=99;var1   +  var2=     var3   ;"
for _1, _2, _3, _4, _5 in string.gmatch(test_str, "(%w+)%s*([%+|%-|%*|%%|%^])%s*(%w+)%s*=%s*(%w+)%s*;%s*([\n]*)") do
	print(_1.._2.._3.."=".._4..";")
end

--[=[
	输出:
	a+b=c;
	1+2=3;
	100-1=99;
	var1+var2=var3;
	]=]

在编写 string.gmatch 那串匹配正则表达式之前,我们可以在 sublime 下演示一下匹配的方式,然后还可以查看替换结果
在这里插入图片描述


string.gsub(s, pattern, repl [, n]) - 替换字符功能

首先吐槽一下,函数名字不太友好

它作用是返回 s 使用 pattern 匹配到的内容(这个返回值可以有多个,也可以根据使用的分组数量来返回匹配的字符串数量),再使用 repl 来替换匹配的内容,n 是要执行替换的分组数量,不填就是使用所有分组

下面给是官方的示例:

     x = string.gsub("hello world", "(%w+)", "%1 %1")
     --> x="hello hello world world"
     
     x = string.gsub("hello world", "%w+", "%0 %0", 1)
     --> x="hello hello world"
     
     x = string.gsub("hello world from Lua", "(%w+)%s*(%w+)", "%2 %1")
     --> x="world hello Lua from"
     
     x = string.gsub("home = $HOME, user = $USER", "%$(%w+)", os.getenv)
     --> x="home = /home/roberto, user = roberto"
     
     x = string.gsub("4+5 = $return 4+5$", "%$(.-)%$", function (s)
           return load(s)()
         end)
     --> x="4+5 = 9"
     
     local t = {name="lua", version="5.4"}
     x = string.gsub("$name-$version.tar.gz", "%$(%w+)", t)
     --> x="lua-5.4.tar.gz"

下面是我自己的测试用例:


function test_expr(n)
	local exp1 = "My Name is : xxx,My Name is : xxx2"

	local repl_str, repl_count

	-- using function
	print("=== using function ===")
	repl_str, repl_count = string.gsub(exp1, "My Name is%s*:%s*(%w+)", function(name) print("Capture your name : " .. name) return "\""..name.."\"" end, n)
	print("repl_str:"..repl_str)
	print("repl_count:"..repl_count)

	-- using table
	print("=== using table ===")
	local repl_tbl_data = {xxx="tom", xxx2="jerry"}
	repl_str, repl_count = string.gsub(exp1, "My Name is%s*:%s*(%w+)", repl_tbl_data, n)
	print("repl_str:"..repl_str)
	print("repl_count:"..repl_count)

	-- using string1
	print("=== using string1 ===")
	repl_str, repl_count = string.gsub(exp1, "My Name is%s*:%s*(%w+)", "uniform_name", n)
	print("repl_str:"..repl_str)
	print("repl_count:"..repl_count)

	-- using string2
	print("=== using string2 ===")
	repl_str, repl_count = string.gsub(exp1, "My Name is%s*:%s*(%w+)", "%0", n) -- %0 is original string content
	print("repl_str:"..repl_str)
	print("repl_count:"..repl_count)

	-- using string3
	print("=== using string3 ===")
	repl_str, repl_count = string.gsub(exp1, "My Name is%s*:%s*(%w+)", "%1", n) -- %1 is the number of the match group
	print("repl_str:"..repl_str)
	print("repl_count:"..repl_count)
end

print("============ test_expr() ======")
test_expr()

print("============ test_expr(0) ======")
test_expr(0)

print("============ test_expr(1) ======")
test_expr(1)

print("============ test_expr(2) ======")
test_expr(2)

--[=[
	============ test_expr() ======
	=== using function ===
	Capture your name : xxx
	Capture your name : xxx2
	repl_str:"xxx","xxx2"
	repl_count:2
	=== using table ===
	repl_str:tom,jerry
	repl_count:2
	=== using string1 ===
	repl_str:uniform_name,uniform_name
	repl_count:2
	=== using string2 ===
	repl_str:My Name is : xxx,My Name is : xxx2
	repl_count:2
	=== using string3 ===
	repl_str:xxx,xxx2
	repl_count:2
	============ test_expr(0) ======
	=== using function ===
	repl_str:My Name is : xxx,My Name is : xxx2
	repl_count:0
	=== using table ===
	repl_str:My Name is : xxx,My Name is : xxx2
	repl_count:0
	=== using string1 ===
	repl_str:My Name is : xxx,My Name is : xxx2
	repl_count:0
	=== using string2 ===
	repl_str:My Name is : xxx,My Name is : xxx2
	repl_count:0
	=== using string3 ===
	repl_str:My Name is : xxx,My Name is : xxx2
	repl_count:0
	============ test_expr(1) ======
	=== using function ===
	Capture your name : xxx
	repl_str:"xxx",My Name is : xxx2
	repl_count:1
	=== using table ===
	repl_str:tom,My Name is : xxx2
	repl_count:1
	=== using string1 ===
	repl_str:uniform_name,My Name is : xxx2
	repl_count:1
	=== using string2 ===
	repl_str:My Name is : xxx,My Name is : xxx2
	repl_count:1
	=== using string3 ===
	repl_str:xxx,My Name is : xxx2
	repl_count:1
	============ test_expr(2) ======
	=== using function ===
	Capture your name : xxx
	Capture your name : xxx2
	repl_str:"xxx","xxx2"
	repl_count:2
	=== using table ===
	repl_str:tom,jerry
	repl_count:2
	=== using string1 ===
	repl_str:uniform_name,uniform_name
	repl_count:2
	=== using string2 ===
	repl_str:My Name is : xxx,My Name is : xxx2
	repl_count:2
	=== using string3 ===
	repl_str:xxx,xxx2
	repl_count:2
]=]

从 test_expr(1) 与 test_expr(2) 可以看出来 n 参数的作用就是使用分组数量的参数


Custom split(s, ss) - 自定义分割函数

通过前面的测试,我们可以使用 string.gmatch 来匹配分割字符的功能

local test_str = "1;2;3"
for v in string.gmatch(test_str, "([^;]*)") do
	if v ~= "" then -- pass empty
		print("match str : " .. v)
	end
end

--[=[
	输出:
	match str : 1
	match str : 2
	match str : 3
]=]

那么我们可以自己封装一个函数 Split(s, ss)

  • s 是我们需要分割的原文
  • ss 是我们需要匹配的分割符,可以是正则(这就很方便了,不过一般很少使用正则来所分割符匹配,一般就写死一个字符或是字符串就好)
function split(s, ss)
	local ret = {}
	for v in string.gmatch(s, "[^"..ss.."]*") do
		-- print("v:" .. v)
		if v ~= "" then -- pass empty
			-- print("match str : " .. v)
			table.insert(ret, v)
		end
	end
	return ret
end

local test_str = "Tom;Jerry;Tony;Jacky"

local split_ret = split(test_str, ";") -- 不需要分组() 了,因为用不上
for i=1, #split_ret do
	print("split_ret[" .. i .. "]=" .. split_ret[i])
end

--[=[
	输出:
	split_ret[1]=Tom
	split_ret[2]=Jerry
	split_ret[3]=Tony
	split_ret[4]=Jacky
]=]
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值