Lua字符串和Lua正则
回到:
字符串
在Lua中,字符串是不可变的,所以相同内容的字符串在lua进程的内存中只有一份。
1 | a,b,c = "hello","hello","hello" -- (a,b,c) --> "hello" |
因为字符串不可变,所以任何带有修改性质的字符串操作,都会创建一个新的字符串。
字符串字面量
字符串可使用单引号、双引号包围,它们在效果上等价。
1 | "a\tb" --> a b |
支持\ddd
格式的字符。例如:
1 | "a\039b" --> a'b |
还可以使用[[]]
包围字符串,类似于here doc,它允许换行,允许出现单双引号。
1 | a = [[ |
但是不能出现]]
,为了允许长字符串里面也能出现]]
,可加上一个或多个=
号,结尾处也对应加上同样数量的等号。
1 | a = [=[ |
但这时又不能出现]=]
,为了允许出现这个符号,多加几个等号:
1 | a = [==[ |
字符串基本操作
使用..
运算符可以连接两个字符串:
1 | a="hello " |
使用长度运算符#
可以计算字符串的长度(也用于计算数组长度),它返回的是字节数量,而不是字符数量:
1 | a="hello" |
如果要返回字符数量,可使用utf8标准库的len函数,例如utf8.len("我是")
返回2。
使用tostring(arg1)
会尝试将arg1转换成字符串类型。
1 | tostring(3.3) --> 3.3 |
字符串标准库string
最常用的几个函数:
1 | string.byte(), string.char() |
上面这些函数也可以写成面向对象语法。比如string.sub(s,1,-1)
的等价写法是s:sub(1,-1)
。
string库的基本操作
string.lower()
和string.upper()
改变字符串大小写。
string.rep(str,N)
重复str字符串N次。
1 | string.rep("a", 3) --> aaa |
string.sub(str,i,j)
表示提取str中从索引i开始到索引j结束的子串,lua中索引都从1开始,而不是0,索引可以是负数索引,-1表示最后一个字符。字符串是不可变的,所以string.sub()返回的是新字符串,不会原处修改。
1 | s = "junmajinlong" |
char()和byte()
string.char(n1,n2,n3,...)
接受一个或多个整数,然后将每个整数转换为对应的字符,最后返回这些字符组成的字符串。
1 | string.char(65,66,67) --> ABC |
string.byte(str,N)
返回str中第N个字符对应的整数值,如果不给N参数,则返回第一个字符的整数值。string.byte(str,i,j)
返回str中从索引i到索引j之间所有字符的整数值。
1 | string.byte("ABC") --> 65 |
find()和match()
find()用于”正则”搜索字符串,它返回搜索到的第一个子串的起始和结束索引位置,搜索失败则返回nil。
lua为了保证语言的精巧,它的”正则”不是正则,是lua自己实现的模式搜索表达式(600行代码不到,POSIX正则4000多行),功能上是一个比较精简的正则表达式。
例如,find()搜索子串:
1 | string.find("jun ma jin long", " [a-z]+ ") --> 4 7 |
find()有两个可选参数,第三个参数表示从哪个索引位置处开始搜索,第四个参数是布尔值,为true时表示精确搜索而非”正则”搜索。
1 | s = "jun ma jin long" |
match()
match()和find()基本类似,但match()返回搜索到的第一个子串,搜索失败返回nil。如果有分组捕获,则返回所有分组捕获到的内容。
1 | string.match("good 12 Job 34", "%d%d") --> 12 |
gsub()
gsub(str, lua_pattern, replacement)
全局替换匹配成功的字符串。还有可选的第四个参数,限制替换的次数。
gsub()返回替换后的字符串,同时返回替换的次数。如果匹配失败,则返回字符串本身,且第二个返回值为0。
1 | s = "junmajinlong" |
gsub()的replacement中,可以使用%0 %1 %2 %3
等这样的分组捕获的反向引用,其中%0
引用的是整个匹配到的内容。
例如,移除字符串前缀、后缀空白:
1 | s = " hello world " |
gsub()的replacement部分,还可以是一个函数或者一个table:
- 如果是table,则将匹配到的字符串作为key,并以table中该key对应的value做替换
- 如果是函数,则将匹配到的字符串作为参数传递给函数,并以函数返回值做替换
- 如果table中该key不存在(或其值为nil),或函数的返回值为nil,则不进行替换
例如,将匹配到的内容转换为大小:
1 | s = "hello" |
gmatch()
string.gmatch(s,pattern)
返回一个可迭代的函数,每次迭代的内容是匹配到的内容。
例如,找出所有大写字母:
1 | s = "Perl Python Shell Ruby Lua" |
UTF8标准库
Lua 5.3引入了utf8标准库,可以处理Unicode字符。
它支持如下几个函数:
1 | utf8.len |
utf8.len()
返回字符数量:
1 | utf8.len("acb") --> 3 |
utf8.char()类似于string.char(),utf8.codepoint()类似于string.byte(),但注意,它们都使用字节索引,如果要使用字符索引,使用utf8.offset(),它返回指定字符索引位置处字符的起始字节索引值。
1 | utf8.codepoint("我是") --> 25105 返回第一个字符的整数 |
utf8.codes()用于迭代utf8字符串中的每个codepoint值。
1 | s = "我是中国人" |
Lua”正则”
Lua使用百分号代替反斜线作为转义符号。例如%.
匹配字符点。
支持如下元字符:
1 | % 转义符号 |
支持如下一些字符类:
1 | %l 匹配小写字母 |
它们全都有大写方式表示对应的补集,例如%L
表示匹配除小写字母外的任意字符:
1 | string.gsub("jun Ma 123","%L","x") --> junxxaxxxx 6 |
此外,Lua还支持两种特殊的模式:
1 | %bxy 匹配从x开始到y结束的子串,如%b()匹配括号和括号内的东西 |
例如,对于%bxy
来说:
1 | s = "a (b (c and d) e) f" |
对于%f[set]
来说:
1 | string.gsub("ab12cd34ef", "%f[%d]", "_") |