首先要知道string.sub 和 string.byte 的用法。
基本思路:
之所以要自己寫一個截取函數,是因為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字節 0xxxxxxx 0 - 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 char then return 0 end local code = string.byte(char) if code < 127 then return 1 elseif code <= 223 then return 2 elseif code <= 239 then return 3 elseif code <= 247 then return 4 else -- 講道理不會走到這里^_^ return 0 end end function StringHelper.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 - 1 then byteStart = bytes+1; elseif index == endIndex then byteEnd = bytes; break; end bytes = bytes + StringHelper.GetBytes(tempStr) tempStr = string.sub(str, bytes+1) index = index + 1 end return string.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