Lua极简入门(十二)——string类库

string类库

这里描述的都是string模块提供的功能,在使用的时候具有两种形式。

print("hello":len())
-- 5
print(string.len("hello"))
-- 5

之后这里都采用string.len(s)这种形式

基础字符串功能

方法 描述
string.len(s) 获取字符串s的长度
string.upper(s) 将字符串s转换为大写,遵循区域设置
string.lower(s) 将字符串s转为小写,遵循区域设置
string.rep(s, n, sep) 对s进行n次重复,如果有sep,则在每次重复之间添加sep
string.sub(s, i, j) 对字符串s进行截取,返回从第i位置开始,到j位置结束的子字符串
string.reverse(s) 对字符串s进行反转
string.byte(s, i, j) 返回字符串中位置i的内部数值,当j指定时,返回位置之间所有字符的内部数值
string.char(...) 与byte相反,由数值转为字符
string.format(formatstring, ...) 格式化字符串,%f浮点数,%d十进制,%x十六进制,%o八进制,%s字符串
  • 字符串长度计算
local str = "hello lua!"
print(string.len(str))
-- 10
  • 字符串大小写转换

字符串大小写转换方法lowerupper可以实现字符串转为小写或大写,不改变原始字符串,返回一个转换后的副本。这两个方法均遵循本地区域设置,如中文地区,其汉语拼音大小写将都按本地拼音规则,不改变。

local str = "hello LUA!中国拼音mǎ yü"
print(string.lower(str))    -- 注意ǎ,ü
-- hello lua!中国拼音mǎ yü
print(string.upper(str))
-- HELLO LUA!中国拼音Mǎ Yü
  • 字符重复方法

rep方法可以快速实现一个指定字符串重复指定次数的拼接,并返回拼接后的字符串。如果需要快速生成一些测试数据时,可以使用该函数。

local str = "hello lua."
print(string.rep(str, 3))
-- hello lua.hello lua.hello lua.
print(string.rep(str, 3, "你好"))
-- hello lua.你好hello lua.你好hello lua.

-- 如果有需要生成一个1G的文档,用于测试上传性能,可以使用rep
local data = string.rep("a", 1024*1024*1024)
  • 字符串截取方法

sub方法用于截取子字符串,i值为开始截取的位置,子字符串包括该位置,从1开始。j表示截取的终止位置,包括该。ij均支持取负值,表示从尾部开始计算,当都是正数或负数时满足i<=j;这一点同redis的位置获取方式一致。正负取值可以混用,如获取一个字符的全部可以简化为sub(1, -1)。j超过总长度时,默认返回全部字符串

该方法不会改变原有的字符串,只返回一个新创建的副本字符串。

local str = "hello lua."
print(string.sub(str, 1, 5))
-- hello
print(print(string.sub(str, -4, -1)))
-- lua.
print(string.sub(str, 1, -1))
-- hello lua.
  • 字符串反转
local str = "hello lua."
print(string.reverse(str))  -- 实现字符串反转,返回一个副本,不改变原始字符串
-- .aul olleh
  • 字符、内部数值相互转换方法

char可以将内部数值(如ASCII)转为字符,byte可以将字符串中指定位置的字符转为内部数值。两者相互转换。

byte(str, i, j)接收一个字符串,两个位置,当两个位置都忽略时,默认转换第一个字符;i为起始位置,从1开始,当j缺省时,只转换第i个字符,并将转换结果返回;当j传入时,转换从ij中间的所有字符,包括起止位置。j超过总长度时,默认返回全部字符串i,j取值规则同sub方法一致,支持负数。

local str = "a dog."
print(string.byte(str))
-- 97
print(string.byte(str, 2))  -- 空格
-- 32
print(string.byte(str, 1, 3)) -- a空格d
-- 97   32  100
local t, j, k = string.byte(str, 1, 3)
print(t, j, k)
-- 97   32  100
print(string.byte(str, 1, -1)) -- 全部
-- 97   32  100 111 103 46
print(string.byte(str, 5, 10)) -- 最后两个字符
-- 103  46

char(...)可以实现传入任意内部数值(ASCII)转为字符串,和byte方法刚好相反。该方法不能对超过2K的字符串进行操作。

print(string.char(97, 98, 99))
-- abc
  • 格式化字符串

format方法用于格式化字符串,使用上同java的格式化方法基本上一致。

local f = "《%s》, reading process:%.2f%%, The page:%4d/%4d"
print(string.format(f, "hello lua", 50.126, 512, 1000))
-- 《hello lua》, reading process:50.13%, The page:0512/1000

支持的格式操作有

格式 描述
%c 接收数字,并转为ASCII对应字符
%d|%i 接收并格式化整数,有符号,%02d-格式化2位,补足补0
%o 八进制
%u 格式化整数,无符号
%x|%X 十六进制,小写|大写表示
%f 浮点数,%.4f,其中4为有效数字
%q 接受一个字符串并将其转化为可安全被Lua编译器读入的格式
%s 字符串
%e|%E 科学记数法标识,e小写,E大写
%g|%G %G对应%E,格式化时为%e或%f中较短的一种
%% 输出%,相当于转义

字符串查找

Lua的字符串查找被称为模式匹配,类似于正则,但不等于,会比正则的范围小。

方法 描述
string.find(s, pattern, start) 在字符串中搜索模式,start默认为1,从那个位置开始搜索,返回搜索到的位置起止位置,未找到返回nil
string.match(s, pattern) 在字符串中搜索模式,返回匹配的字符串
string.gsub(s, pattern, repl,n) 替换方法,在字符串中搜索模式,匹配后使用repl进行替换
string.gmatch(s, pattern) 查找模式,并返回函数,用于迭代所有匹配的字符串
  • 模式

Lua中字符串的查找,主要是用模式进行匹配,同正则有关联,也有不同,通常情况下直接使用字符串字面值表示也能完成大部分查找需求,但总有需要更加有效的场景,如查找数字等。在实现Lua字符查找时,不能借助Java中的正则经验,需要从Lua支持的字符分类中去编写适配的模式,下表为Lua支持的字符分类。

最简单的模式就是字符串的字面值

模式 描述
%a 字母
%c 控制字符
%d 数字
%l 小写字母,支持本地化,如拼音
%p 标点符号
%s 空白字符
%u 大写字母
%w 字母和数字
%x 十六进制数字
%z 内部表示0的字符

如果将上述分类中的字母大写,如%W,表示对%w的补集,即既不是字母也不是数字,其他类似。

local str = "hello world34"
local nonChar = "%A"    -- 该模式可以查找空格,3、4
local num = "%d"    -- 可匹配3、4
local space = "%s"  -- 可匹配空格
local str2 = "hello。."
local b = "%p"  -- 可匹配标点符号. 无法匹配中文句号,中文占3个字符位置

(、)、[、]、.、+、-、*、%、?、$、^

这些字符为特殊字符,需要转义,使用%转义,如%( 匹配左括号

和正则一致,采用[]用于描述字符集,如[ABC]匹配大写字母A、B、C,[%w]匹配字母和数字。集合支持范围,如[A-F]表示只在A、F及之间的大写字母。在字符集前加上^表示补集,如[^A-F]表示A-F及之间大写字母外的其他任意字符。

local str = "A123acB34dC"
print(string.find(str, "[ABC]", 2))
-- 7 7

同正则一样,模式也可以使用修饰符来对集合等进行限制,其支持的装饰符如下

修饰符 描述
+ 重复一次及多次
出现0次或1次
* 重复0次或多次
- 重复0次或多次
local str = "A123acB34dC"
print(string.find(str, "%d+"))
-- 2 4

$字符来匹配结尾,如%d$,只匹配结尾,如果结尾是数字,则返回位置,否则为nil(这里指find)

%b也是模式中的一个特殊标识,用于成对匹配,方式为%b<x><y>,成对的字符分别为x\y

local str = "tia,[hello world]."
print(string.find(str, "%b[]"))
-- 5 17
  • find,查找字符串位置

find方法用于查找模式,匹配到,返回第一个找到的起始位置和终止位置,未找到时,返回nil,如果出现第三个参数,表示从第几个字符位置开始查找。

local str = "hello lua"
print(string.find(str, "lua"))
-- 7 9
print(string.find(str, "l"))    -- 第一个l位置为3
-- 3 3
print(string.find(str, "oa"))
-- nil
print(string.find(str, "%s"))   -- 空格
-- 6 6

使用指定搜索位置参数,查找一个字符串中所有匹配的位置集合

-- 查找字符串中出现ll的所有位置
local str = "smell small well pull."

local pos = {}
local p = "ll"
local index = 1
while true do
    local i, j = string.find(str, p, index)
    if i == nil then
        break
    end
    pos[#pos + 1] = {
        start = i,
        over = j
    }
    index = j + 1
end

for _, v in pairs(pos) do
    print(v.start, v.over)
end
-- 4    5
-- 10   11
-- 15   16
-- 20   21
  • match,查找字符串

match函数在一个字符串中查找模式,和find函数基本类似,返回的结果时匹配到的字符串。

local str = "hello lua.lua"
print(string.match(str, "lua"))
-- lua

由于模式就是字符串字母值,因此一旦匹配上,返回的就是模式本身。当使用字符分类时,则与次就有所不同。

-- 采用模式,查找连续数字的字符串
local str = "hello lua.lua,33 page,total 123"
print(string.match(str, "%d+"))
-- 33
  • gsub,替换字符串

gsub方法,将使用模式在字符串中查找所有匹配的位置,使用替代字符串进行替换。返回替换后的字符串,第二个返回值为替换的次数。gsub还有一种重载形式,传入第四个参数,用于限制替换的次数。

-- 将所有字符l替换为a
local str = "hello lua."
print(string.gsub(str, "l", "a"))
-- heaao aua.   3
-- 只替换2次,最后一个l未被替换
print(string.gsub(str, "l", "a", 2))    
-- heaao lua.   2

基于gsub的特性,可以使用gsub用于统计字符串中某些字符的个数。string.gsub(str, 'a', 'a'),返回的第二个值即为字符串中a出现的次数。

  • gmatch,查找模式并返回函数用于迭代遍历所有找到的字符
local str = "hello lua."
print(string.gmatch(str, "l"))
-- function: 00000000007f9580

使用该方法,查找一段文本中,所有的出现的数字集合。

local str = "在 2019 年已经逐渐成为共识,Redmi K30 第一个亮点就在于其采用了 6.67 英寸 120Hz 刷新率 LCD 屏幕"
local nums = {}
for num in string.gmatch(str, "%d+") do
    nums[#nums + 1] = num
end
for _, v in pairs(nums) do
    print(v)
end
-- 2019
-- 30
-- 6
-- 67
-- 120
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343

推荐阅读更多精彩内容

  • 基础知识 Lua中的string和c#中相同,string类型的值一旦改变,便要为新值开辟空间,并指向此空间。也就...
    Charon_ted阅读 1,027评论 0 1
  • Lua 5.1 参考手册 by Roberto Ierusalimschy, Luiz Henrique de F...
    苏黎九歌阅读 13,733评论 0 38
  • string库提供了字符串处理的通用函数。 例如字符串查找、子串、模式匹配等。 当在 Lua 中对字符串做索引时,...
    chiguozi阅读 3,818评论 0 3
  • Lua 5.3 参考手册 http://www.runoob.com/manual/lua53doc/manual...
    passiony阅读 1,036评论 0 0
  • 官网 中文版本 好的网站 Content-type: text/htmlBASH Section: User ...
    不排版阅读 4,365评论 0 5