lua

lua字符串骚操作

Posted by myc on November 6, 2020

lua中的字符串

在lua中字符串的类型是 string ,通常字符串的拼接是通过.. 例如

local str = "te"
local str2 = "st"

local str3 = str .. str2
print(str3) --输出 test

print(type(str3)) --输出 string

但是其实很少有人关注,字符串其实是一个表,可以 getmetatable 获取到相应的原表

local str = ""

local mt = getmetatable(str);

而且有意思的是普通字符串相应的原表的__index居然是 string 库,这意味则,其实普通字符串可以直接调用string库接口,而且扩展了string库,那么普通字符串也具有相关功能(原表原理)。 基于此原理,我们可以对字符串进行扩展实现一些骚操作,例如下面的代码


local tmp = "test"

local str = "stringtest";

local mt = getmetatable(tmp);
print(mt.__index)
print(string)
if mt.__index == string then
	print("普通字符串的原表元方法__index是string")
end

print(str[1]) --输出是nil

--扩展元方法__index
mt.__index = function(str, i)
    if (type(i) == 'number') then
        return string.sub(str, i, i)
    end
    return string[i]
end

--再次验证str[1]
print(str[1]) --输出是 s



---实现函数调用式字符串截取

-- local b = str(2,5) --此时运行会报错 attempt to call local 'str' (a string value)

--扩展元方法__call
mt.__call = function(str, i, j)
    if (type(i) == 'number' and type(j) == 'number') then
        return string.sub(str, i, j)
    elseif (type(i) == 'number' and type(j) == 'string') then
        return table.concat{string.sub(str, 1, i - 1), j, string.sub(str, i + 1)}
    elseif (type(i) == 'number' and type(j) == 'nil') then
        return string.byte(str, i)
    end

    return string[i]
end

local b = str(2,5);
print(b) -- 输出 trin

---实现字符串加法
-- local b = tmp + str  --此时运行会报错 attempt to perform arithmetic on local 'tmp' (a string value)

--扩展元方法__add
mt.__add = function(str1, str2)
	return table.concat({str1,str2})
end

local b = tmp + str
print(b) -- 输出 teststringtest

---实现字符串减法
-- local b =  str - tmp  --此时运行会报错 attempt to perform arithmetic on local 'str' (a string value)

--封装一下简单的字符串移除接口
--[[--
	移除str中符合pattern模式的子串,最多不超过limit个
	@tparam string str 目标字符串
	@tparam string pattern 匹配模式
	@tparam number limit 移除上限
	@return string 移除后的字符串
	@usage
	string.remove("213123xi","3",1) -- "21123xi"
]]
function string.remove(str, pattern, limit)
    if (pattern == '' or pattern == nil) then
        return str
    end

    if (limit == '' or limit == nil) then
        str = string.gsub(str, pattern, '')
    else
        str = string.gsub(str, pattern, '', limit)
    end
    return str
end

--扩展元方法__sub
mt.__sub = function(str1, str2)
	return str1:remove(str2) -- 这里的调用方式等价于 string.remove(str1,str2)
end

local b = str - tmp
print(b) -- 输出 string

--实现字符串分割
--[[--
	按照分隔符delimiter分割字符串成table
	@tparam string str 目标字符串
	@tparam string delimiter 分隔符
	@return table 被分割的表
	@usage 
	local a = string.split("axbxc","x")
	a = {a,b,c} 
]]
function string.split(str, delimiter)
    if (delimiter == '') then return false end
    local pos, arr = 0, {}
    -- for each divider found
    for st, sp in function() return string.find(str, delimiter, pos, true) end do
        table.insert(arr, string.sub(str, pos, st - 1))
        pos = sp + 1
    end
    table.insert(arr, string.sub(str, pos))
    return arr
end

local path = "c:\\user\\tmp\\lua"

local list = path:split("\\") --此时list 等于 {c:,user,tmp,lua}
for i,v in ipairs(list) do
	print(i,v)
end

--以下是测试string自带接口

--字符串全部转为大写字母
local b = str:upper()
print(b) -- 输出 STRINGTEST

--找到索引
local i = str:find("test")
print(i)-- 输出 7

--在字符串中替换
local b = str:gsub("test","lua")
print(b) -- 输出 stringlua