Lua中string库以及应用
一、不需要模式匹配的函数
1. string.byte() —— 字符转换为编码(ASCII码)
原型:string.byte (s [, i [, j] ])
函数返回字符s[i], s[i+1], ···, s[j]
的内部数字编码(ASCII码),其中参数i的默认值是1,而参数j的默认值是i
local str = "012abcd"
print("\n常规1~4的编码(012a):")
print(string.byte(str,1,4))
-- 字符串处理库的所有函数都被放置在表string中,并且还为操作的字符串设置了元表,使得这些字符串有了一个指向表string的__idnex字段
print("\n面向对象的表现方式:")
print(str:byte(1,4))
print("\n使用负数索引(c,d):")
print(str:byte(-2,-1))
2. string.char() —— 将编码(ASCII码)转化为字符
原型:string.char(...)
接收0个或者多个参数,返回一个字符串,字符串长度等于参数个数,前提是每一参数作为ASCII码都有一个字符与之相对应,也就是说大部分的数字是无效的,
local str = "012abcd"
print("\n常规1~4的编码(012a):")
print(string.byte(str,1,4))
-- 字符串处理库的所有函数都被放置在表string中,并且还为操作的字符串设置了元表,使得这些字符串有了一个指向表string的__idnex字段
print("\n面向对象的表现方式:")
print(str:byte(1,4))
print("\n使用负数索引(c,d):")
print(str:byte(-2,-1))
3. string.format()——格式化字符串。
原型:string.format (formatstring, ···)
格式化的字符串和C语言的printf()一族的函数遵循相同的规则
各种参数选项的含义:
c(字符) d(有符号数字) e(指数形式标书数字,小数点后6位有效数字)
E(与e相同,在数字表示中用E代替e)f(不使用指数表示数字,小数点后6位数字)g(指数形式标书数字,保留6位有效数字)
G(与g相同,在数字表示中用E代替e)i(测试与d相同)
o(八进制打印) u(无符号数字) x(十六进制表示)
– q (可以显示几乎所有特殊字符,并且不需要特殊处理。)
-- 打印字符串
local retstr = string.format("\ntoday is %s", os.date())
print(retstr)
---普通的字符串如果遇到字符"\0"时将会被截断,想要不截断那就需要使用格式符%q来处理
local sourcestr = "ADGdfhhjfhjafhdf~fa\000fFAKLDSFklj897890"
print("\n原串: "..sourcestr)
local q_sourcestr = string.format("%q", sourcestr)
print("\n格式化后不会被截断 "..q_sourcestr)
4. string.lower()——大写转小写
5. string.upper()——小写转大写
6. string.rep()——字符串的复制拼接
原型:string.rep(s, n)
返回字符串s串联n次的所组成的字符串,参数s表示基础字符串,参数n表示赋值的次数。
7. string.reverse()——字符串的复制拼接
原型:string.reverse(s)
返回字符串s
反序字符串
-- 普通字符串
local sourcestr = "I am a good person !"
print("\nsourcestr is : "..sourcestr)
-- 使用函数反转
local first_ret = string.reverse(sourcestr)
print("\nfirst_ret is : ")
print(first_ret)
-- 字符串里包括`\0`
local otherstr = "this is a string \0 hahaha "
print("\n\notherstr is : "..string.format("%q", otherstr))
-- 再次使用函数反转
first_ret = string.reverse(otherstr)
print("\nfirst_ret is : ")
print(string.format("%q", first_ret))
8. string.reverse()——字符串截取
原型:string.sub(s, i [, j])
返回: s中从第i个字符到第j个字符的子串,
特殊:string.sub(s, 1, j)是返回字符串长度为j的前缀, string.sub(s, -i)返回子串长度为i的原串的后缀。
local sourcestr = "prefix--de asdsdjjj\0dsfdf56\0mfa54--suffix"
print("\n显示源字符串", string.format("%q", sourcestr))
local first_sub = string.sub(sourcestr, 4, 25)
print("\n普通截取", string.format("%q", first_sub))
local second_sub = string.sub(sourcestr, 1, 8)
print("\n取8个长度", string.format("%q", second_sub))
local third_sub = string.sub(sourcestr, -10)
print("\n从后取10个", string.format("%q", third_sub))
local fourth_sub = string.sub(sourcestr, -100) --函数会选择最接近指定索引的的一个索引作为参数。
print("\n索引越界", string.format("%q", fourth_sub))
9. string.dump()——序列化字符串
原型:string.dump (function)
序列化 (Serialization)将对象的状态信息转换为可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。可以通过从存储区中读取或反序列化对象的状态,重新创建该对象
--自定义一个函数
local function custom_func(num1, num2)
local ret = num1 + num2;
print("\nnum1 = "..num1)
print("num2 = "..num2)
print("num1 + num2 = "..ret)
end
-- 将函数序列化
local func_content = string.dump(custom_func)
print("\nfunc_content = "..func_content)
-- 将转化后的字符串写入文件
local outfile = io.open("dumptest.txt", "w")
local outnum = outfile:write(func_content)
outfile:close()
-- 从文件总读取内容
local infile = io.open("dumptest.txt", "r")
local incontent = infile:read("*a")
infile:close()
print("\ninput content is "..incontent)
二、模式匹配的函数
模式匹配函数
在string库中功能最强大的函数是:string.find (字符串查找)
, string.gsub (全局字符串替换)
,and string.match() (字符串匹配).
与其他脚本语言不同的是,Lua并不使用POSIX规范的正则表达式(也写作regexp)来进行模式匹配(译者:POSIX是unix的工业标准,regexp最初来源于unix,POSIX对regexp也作了规范)。
主要的原因出于程序大小方面的考虑:实现一个典型的符合POSIX标准的regexp大概需要4000行代码,这比整个Lua标准库加在一起都大。权衡之下,Lua中的模式匹配的实现只用了500行代码,当然这意味着不可能实现POSIX所规范的所有更能。然而,Lua中的模式匹配功能是很强大的,并且包含了一些使用标准POSIX模式匹配不容易实现的功能。
1. string.find()——字符串查找
原型:string.find (s, pattern [, init [, plain]])
s:目标串 ;pattern:查找串; init(可选):搜索的起始位置 ;plain(可选):模式匹配的开闭
匹配模式:如果开启了匹配模式(false), %d 会被认为 是查找一个数字, 关闭了(true),那就是查找有无 %d
返回:查找的第一个起始索引和结束索引,如果模式匹配子串被找到了,一个成功被找到的子串将会作为第三个返回值;返回 第三个值的条件,那就是参数pattern中必须包括字符"()",这是输出第三个返回值的必要条件。
local i, j=string.find("456 hello world! 123", 'l')
print("---查找 l----",i, j)
local i, j=string.find("456 hello world! 123", 'l',10)
print("---查找 l(10)----",i, j)
local i, j=string.find(" hello 456 %d world! 123", '%d')
print("---查找 %d(匹配模式默认开启)----",i, j) -- 找到的是4的坐标
local i, j=string.find(" hello 456 %d world! 123", '%d',1,true)
print("---查找 %d(匹配模式关闭)----",i, j) -- 找到的是 %d 字符的坐标
local i, j, val=string.find(" hello 456 %d world! 123", '(%d)')
print("---查找 %d----",i, j,val) -- 加上() 可返回匹配模式查找到的数值
2. string.gsub()——查找子串并替换
原型:string.gsub (s, pattern, repl [,m])
不会对原串有改动
s:目标串 pattern:模式串 repl:替换串(一个字符串、表、或者是函数) m : 表示替换多少个
返回:1:替换后的副本 2:匹配替换的次数
解释:这个函数会返回一个替换后的副本,原串中所有的符合参数pattern
的子串都将被参数repl
所指定的字符串所替换,如果指定了参数m
,那么只替换查找过程的前m
个匹配的子串,参数repl
可以是一个字符串、表、或者是函数,并且函数可以将匹配的次数作为函数的第二个参数返回,接下来看看参数repl
的含义:
如果参数repl
是一个常规字符串,成功匹配的子串会被repl
直接替换,如果参数repl
中包含转移字符%
,那么可以采用%n
的形式替换,当%n
中的n
取值1-9时,表示一次匹配中的第n个子串,当其中的n
为0时,表示这次匹配的整个子串,%%
表示一个单独的%
。
如果参数repl
是一个表,那么每次匹配中的第一个子串将会作为整个表的键,取table[匹配子串]来替换所匹配出来的子串,当匹配不成功时,函数会使用整个字符串来作为table的键值。
如果参数repl
是一个函数,那么每一次匹配的子串都将作为整个函数的参数,取function(匹配子串)来替换所匹配出来的子串,当匹配不成功时,函数会使用整个字符串来作为函数的参数。如果函数的返回值是一个数字或者是字符串,那么会直接拿来替换,如果它返回false
或者nil
,替换动作将不会发生,如果返回其他的值将会报错。处。
local x
x = string.gsub("hello world", "o", "lua")
print("\n全部替换的常规替换:",x)
x = string.gsub("hello worold", "o", "lua",1)
print("\n只替换一次的常规替换:",x)
x = string.gsub("hello world", "(%w+)", "lua")
print("\n正则表达式替换",x)
-- 如果参数repl中包含转移字符%,那么可以采用%n的形式替换,
-- 当%n中的n取值1-9时,表示一次匹配中的第n个子串,当其中的n为0时,表示这次匹配的整个子串,%%表示一个单独的%。
x = string.gsub("hello world", "%w+", "%1")
print("\n包含转义字符%的替换",x)
x = string.gsub("hello world", "%w+", "%0 %0")
print("\n用匹配出的完成串*2来替换第一次匹配的结果",x)
x = string.gsub("hello world from c to lua", "(%w+) (%a+)", "%0 %2")
print("\n使用一个完整匹配和一个匹配的第二个串来替换",x)
-- 如果参数repl是一个函数,那么每一次匹配的子串都将作为整个函数的参数,
-- 取function(匹配子串)来替换所匹配出来的子串,当匹配不成功时,函数会使用整个字符串来作为函数的参数。
-- 如果函数的返回值是一个数字或者是字符串,那么会直接拿来替换,如果它返回false或者nil,替换动作将不会发生,
-- 如果返回其他的值将会报错。
x = string.gsub("4 + 5 = $return 4+5$", "%$(.-)%$", function (s)
return load(s)()
end)
print("\n用自定义函数",x)
local t = {name="lua", version="5.1"}
x = string.gsub("$name-$version", "%$(%w+)", t)
print("\n调用表来替换",x)
3. string.match()——高端匹配函数(找第一个,直接返回)
原型:string.match(s, pattern [, init])
s:目标串 pattern:模式串 init:匹配的起始位置
解释:返回一个迭代器函数,每一次调用这个函数,返回一个在字符串s
找到的下一个符合pattern
描述的子串。如果参数pattern
描述的字符串没有找到,迭代函数返回nil
。
local aimStr = "ehre99wj=--=-*-/4mdqwl\0ds123fef"
print("\n目标串 = ".. aimStr)
-- 由第一组结果可以看出string.match()在遇到\0时不会停止查找,
-- 而是一直查找到字符串结尾。
local ret1= string.match( aimStr,"%d%d%d")
print("\n找连续的三个数字 = ".. ret1)
ret1= string.match( aimStr,"%d%a%a")
print("\n找数字字母字母 = ".. ret1)
ret1 =string.match( aimStr,"")
print("\n找空的 = ".. ret1)
ret1= string.match( aimStr,"%d%d",10)
print("\n从10后面找两个数字 = ".. ret1)
print(string.match("hello world", "h(ell)o wor")) --ell
-- 如果pattern没有指定括号,将返回整个匹配内容,否则返回括号内
print(string.match("hello world", "hello"))
-- 模式匹配
print(string.match("hell1o- world", "(%w+)"))
三、拓展
1. Lua中实现字符串分割函数split
function split(input, delimiter)
input = tostring(input)
delimiter = tostring(delimiter)
if (delimiter == "") then return false end
local pos, arr = 0, {}
for st, sp in function() return string.find(input, delimiter, pos, true) end do
table.insert(arr, string.sub(input, pos, st - 1))
pos = sp + 1
end
table.insert(arr, string.sub(input, pos))
return arr
end
local retTable = split("1-2-3-4","-")
for i,v in ipairs(retTable) do
print(v)
end