先添加一个string类的引用(可访问性的区别 主要代码高亮看起来和全局变量不同)
local string = string
---@param str string
---@param delim string
---@return string[]
function string.split(str, delim)
local result_str_list = {}
str:gsub('[^' .. delim .. ']+', function(w)
table.insert(result_str_list, w)
end)
return result_str_list
end
---@param str string
---@param char string? @trim space and newline when 'char' is nil
---@return string, number @result and trim count
function string.trim(str, pattern)
pattern = pattern or '%t+%r+%n+%s+'
return str:gsub(pattern, '')
end
---裁剪空格
function string.trim_space(str)
return str:trim('%s+')
end
---裁剪长度
function string.trim_length(str, max_length)
local length = 0
return str:gsub(utf8.charpattern, function(char)
length = length + #char
return length <= max_length and char or ''
end)
end
---@return boolean
function string.start_with(str, header)
return str:sub(1, #header) == header
end
---@return boolean
function string.end_with(str, header)
return str:sub(#str - #header + 1) == header
end
url的参数以问号后接kv的格式:url?k1=v1&k2=v2,目标是分割URL并提取多组kv值:
---@return string, table<string, string>
function string.parse_url(url)
local params = {}
local segs = url:split('?')
local host = segs[1]
if #segs > 1 then
local param = segs[2]
local param_contents = param:split('&')
for i = 1, #param_contents do
local temp_strs = param_contents[i]:split('=')
if #temp_strs > 1 then
params[temp_strs[1]] = temp_strs[2]
end
end
end
return host, params
end
例如,一个英文字符和一个中文字符都以1来计算。此方法适用于UTF-8编码的字符串:
---@return number
function string.char_count(content)
if not content or type(content) ~= "string" or #content == 0 then
return 0
end
local length = 0
local index = 1
while true do
local cur_byte = content:byte(index)
local byte_count = 1
if cur_byte > 239 then byte_count = 4
elseif cur_byte > 223 then byte_count = 3
elseif cur_byte > 127 then byte_count = 2
end
index = index + byte_count
length = length + 1
if index > #content then
break
end
end
return length
end
local s = "你好,世界"
print(s:len())
print(s:char_count())
-- output --
15
5
中文字符在 Unicode 编码中位于 0xE0xx~0xEFxx,即 244~239,这一段在 UTF8 编码中占用 3 个字节。附上 UTF-8 编码的字节数对应表:
| 字节数 | 编码位(高位) | 编码位(低位) | 高位对应十进制 |
|---|---|---|---|
| 1 | 00~7F | - | 0~127 |
| 2 | C0~DF | 80~BF | 128~223 |
| 3 | E0~EF | 80~BF | 224~239 |
| 4 | F0~FF | 80~BF | 240~255 |
Emoji 虽然也是 Unicode 编码,但是在很多场景中无法正常显示。为了保证内容有时需要进行裁剪。裁剪的方式也很简单,即排除掉 Unicode 中 Emoji 编码位的字符即可。
function string.filter_emoji(str)
return str:gsub(utf8.charpattern, function(char)
local codepoint = utf8.codepoint(char)
if codepoint >= 0x231A and codepoint <= 0x27BF then return '' end
if codepoint >= 0x2B1B and codepoint <= 0x2B55 then return '' end
if codepoint >= 0x1F1E6 and codepoint <= 0x1F1FF then return '' end
if codepoint >= 0x1F300 and codepoint <= 0x1F6FF then return '' end
if codepoint >= 0x1F900 and codepoint <= 0x1FAFF then return '' end
return char
end)
end
当然了由于 Unicode 每个版本都会添加新的 Emoji,编码位也会随之新增,因此通常在版本更新后最好可以将新的编码位剔除。(这是一个年更的 function~)