首先要知道string.sub 和 string.byte 的用法。
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5SM3EzMiRWNidTOxMzM1gDZ4kTO4MDZkdDZzE2YyQWN08CX0JXZ252bj91Ztl2Lc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
基本思路:
之是以要自己寫一個截取函數,是因為lua的庫函數string.sub實際是位元組的截取函數。
uft-8編碼格式中,大部分中文是3個位元組表示的,數字和字母等是一個位元組的,還有某些國家的語言是2位元組的,直接用string.sub就可能截出亂碼來,因為不确定要截多少個位元組。
是以,
定義一個GetBytes函數,擷取字元的位元組數(根據首個位元組的高位标記,判斷是幾位元組的字元)
然後不斷後移,記錄位元組數和字元數。
如上圖,假設要取字元3-4,那麼應該從第3個字元的第一個位元組取到第4個字最後一個位元組
即:
目前字元數為截取的起始字元(startIndex)前一個位置時,說明從下一個位元組開始截取字元串 即 index == startIndex - 1 時 byteStart = bytes+1
目前字元數為截取的終止字元(endIndex)時,說明要截取的字元串到此為止 即 index == endIndex 時 byteEnd = bytes
用 string.sub(str, byteStart, byteEnd) 就能截取byteStart 到 byteEnd 的位元組
local StringHelper ={}--[[
utf-8編碼規則
單位元組-0起頭
1位元組 0xxxxxxx0 - 127多位元組-第一個位元組n個1加1個0起頭2 位元組 110xxxxx 192 - 223
3 位元組 1110xxxx 224 - 239
4 位元組 11110xxx 240 - 247可能有1-4個位元組--]]function StringHelper.GetBytes(char)if not charthenreturn 0end
local code= string.byte(char)if code < 127thenreturn 1elseif code<= 223thenreturn 2elseif code<= 239thenreturn 3elseif code<= 247thenreturn 4
else
-- 講道理不會走到這裡^_^
return 0end
endfunctionStringHelper.Sub(str, startIndex, endIndex)
local tempStr=str
local byteStart= 1 --string.sub截取的開始位置
local byteEnd= -1 --string.sub截取的結束位置
local index= 0 --字元記數
local bytes= 0 --字元的位元組記數
startIndex= math.max(startIndex, 1)
endIndex= endIndex or -1
while string.len(tempStr) > 0 do
if index == startIndex - 1then
byteStart= bytes+1;
elseif index==endIndex then
byteEnd=bytes;break;
end
bytes= bytes +StringHelper.GetBytes(tempStr)
tempStr= string.sub(str, bytes+1)
index= index + 1endreturnstring.sub(str, byteStart, byteEnd)
end
測試代碼:
str = "中1文*a字元串勉強します";
print(StringHelper.Sub(str, 3, 4))
print(StringHelper.Sub(str, 1, 4))
print(StringHelper.Sub(str, 8))
print(StringHelper.Sub(str, 2, 12))
https://www.cnblogs.com/yougoo/p/11960801.html