string.lua 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. string.empty = ''
  2. function string.contains(str, subStr)
  3. return string.find(str, subStr) ~= nil
  4. end
  5. function string.endsWith(str, subStr)
  6. local len1 = #str
  7. local len2 = #subStr
  8. if len1 < len2 then
  9. return false
  10. end
  11. return string.find(str, subStr, len1 - len2 + 1) ~= nil
  12. end
  13. function string.isNullOrEmpty(str)
  14. return str == nil or str == ""
  15. end
  16. function string.replace(str, oldStr, newStr)
  17. local i, j = string.find(str, oldStr, 1, true)
  18. if i and j then
  19. ---@class ret
  20. local ret = {}
  21. local start = 1
  22. while i and j do
  23. table.insert(ret, string.sub(str, start, i - 1))
  24. table.insert(ret, newStr)
  25. start = j + 1
  26. i, j = string.find(str, oldStr, start, true)
  27. end
  28. table.insert(ret, string.sub(str, start))
  29. return table.concat(ret)
  30. end
  31. return str
  32. end
  33. function string.split(str, sep)
  34. sep = sep or " "
  35. local items = {}
  36. local pattern = string.format("([^%s]+)", sep)
  37. string.gsub(str, pattern, function(c)
  38. table.insert(items, c)
  39. end)
  40. return items
  41. end
  42. ---@param pattern string @例如 '<.->',里面的减号表示尽可能少,例如 abc<fdsafdsa>df<dddd> 分割后返回 abc <fdsafdsa> df <dddd>
  43. ---但是 abc<fdd<d>d> 会匹配成 abc <fdd<d> d>
  44. function string.splitPair(str, pattern)
  45. local items = {}
  46. --或者 %b<>
  47. local temp = {}
  48. for v in string.gmatch(str, pattern) do
  49. table.insert(temp, v)
  50. end
  51. local index = 1
  52. local tempIndex = 1
  53. local length = string.len(str)
  54. while index <= length and tempIndex <= #temp and not string.isNullOrEmpty(str) do
  55. local i = string.indexOf(str, temp[tempIndex])
  56. local pre = string.sub(str, 1, i - 1)
  57. if not string.isNullOrEmpty(pre) then
  58. table.insert(items, pre)
  59. end
  60. table.insert(items, temp[tempIndex])
  61. index = i + string.len(temp[tempIndex])
  62. str = string.sub(str, index)
  63. tempIndex = tempIndex + 1
  64. index = i + 1
  65. end
  66. if not string.isNullOrEmpty(str) then
  67. table.insert(items, str)
  68. end
  69. return items
  70. end
  71. ---@return table @abc<fdd<d>d> 会匹配成 abc <fdd<d>d> 完全匹配 left:'<' right:'>'
  72. function string.splitCompletePairMatch(str, left, right)
  73. local items = {}
  74. local index = 1
  75. local length = string.len(str)
  76. local leftCount = 0
  77. local preIndex = 1
  78. while index <= length do
  79. local c = string.sub(str, index, index)
  80. if c == left then
  81. if leftCount == 0 then
  82. if preIndex <= index - 1 then
  83. local pre = string.sub(str, preIndex, index - 1)
  84. preIndex = index
  85. if not string.isNullOrEmpty(pre) then
  86. table.insert(items, pre)
  87. end
  88. end
  89. end
  90. leftCount = leftCount + 1
  91. elseif c == right then
  92. if leftCount ~= 0 then
  93. leftCount = leftCount - 1
  94. if leftCount == 0 then
  95. local p = string.sub(str, preIndex, index)
  96. preIndex = index + 1
  97. table.insert(items, p)
  98. end
  99. else
  100. local p = string.sub(str, preIndex, index)
  101. preIndex = index + 1
  102. table.insert(items, p)
  103. end
  104. end
  105. index = index + 1
  106. end
  107. if preIndex <= length then
  108. local p = string.sub(str, preIndex, length)
  109. table.insert(items, p)
  110. end
  111. return items
  112. end
  113. ---@return string[] @例如 分隔符/,111/aaa 分割之后是 111 /aaa
  114. function string.splitToArray(str, sep)
  115. local items = string.splitPair(str, sep)
  116. local t = {}
  117. local s = string.empty
  118. for k, v in pairs(items) do
  119. if v == sep then
  120. s = v
  121. elseif not string.isNullOrEmpty(s) then
  122. table.insert(t, s .. v)
  123. s = string.empty
  124. else
  125. table.insert(t, v)
  126. end
  127. end
  128. return t
  129. end
  130. ---@return string[] @例如 helloWorld 分隔符llo 分割之后是he World
  131. function string.splitByAll(str, sep)
  132. if type(sep) ~= "string" or #sep <= 0 then
  133. return
  134. end
  135. local index = 1
  136. local strTb = {}
  137. while true do
  138. local pos = string.find(str, sep, index, true)
  139. if not pos then
  140. break
  141. end
  142. table.insert(strTb, string.sub(str, index, pos - 1))
  143. index = pos + string.len(sep)
  144. end
  145. table.insert(strTb, string.sub(str, index))
  146. return strTb
  147. end
  148. function string.getChar(str, index)
  149. return string.sub(str, index, index)
  150. end
  151. function string.startsWith(str, subStr)
  152. return string.find(str, subStr) == 1
  153. end
  154. local EMPTY_CHARS = " \t\n\r"
  155. function string.trim(str, chars)
  156. chars = chars or EMPTY_CHARS
  157. return str:match(string.format("^[%s]*(.-)[%s]*$", chars, chars))
  158. end
  159. function string.trimLeft(str, chars)
  160. chars = chars or EMPTY_CHARS
  161. return str:match(string.format("^[%s]*(.*)", chars))
  162. end
  163. function string.trimRight(str, chars)
  164. chars = chars or EMPTY_CHARS
  165. return str:match(string.format("(.-)[%s]*$", chars))
  166. end
  167. function string.indexOf(s, pattern, init)
  168. init = init or 0
  169. local index = string.find(s, pattern, init, true)
  170. return index or -1;
  171. end
  172. function string.lastIndexOf(s, pattern)
  173. local i = s:match(".*" .. pattern .. "()")
  174. if i == nil then
  175. return nil
  176. else
  177. return i - 1
  178. end
  179. end
  180. ---@return string @顺序匹配是否包含
  181. function string.containsByOrder(str, subStr)
  182. local len = string.len(str)
  183. local subLen = string.len(subStr)
  184. local lenIndex = 1
  185. local subLenIndex = 1
  186. while subLenIndex <= subLen and lenIndex <= len do
  187. local subChar = string.getChar(subStr, subLenIndex)
  188. local char = string.getChar(str, lenIndex)
  189. if subChar == char then
  190. subLenIndex = subLenIndex + 1
  191. lenIndex = 1
  192. else
  193. lenIndex = lenIndex + 1
  194. end
  195. end
  196. if subLenIndex >= subLen then
  197. return true
  198. end
  199. return false
  200. end
  201. function string.insert(str, index, insertStr)
  202. local pre = string.sub(str, 1, index - 1)
  203. local tail = string.sub(str, index, -1)
  204. local createStr = string.format("%s%s%s", pre, insertStr, tail)
  205. return createStr
  206. end
  207. --获取文件名
  208. function string.getFileName(filename)
  209. return string.match(filename, ".+/([^/]*%.%w+)$")
  210. end
  211. function string.getFileNameWithoutExtension(filename)
  212. return string.match(filename, ".+/([^/]*)%.%w+$")
  213. end
  214. --获取扩展名
  215. function string.getExtension(str)
  216. return str:match(".+%.(%w+)$")
  217. end
  218. ---@return string @减少无效匹配的gc分配
  219. function string.gsub_opti(s, pattern, repl, n)
  220. if string.contains(s, pattern) then
  221. return string.gsub(s, pattern, repl, n)
  222. else
  223. return s
  224. end
  225. end
  226. ---@return string @减少无效匹配的gc分配
  227. function string.gmatch_opti(s, pattern)
  228. if string.contains(s, pattern) then
  229. return string.gmatch(s, pattern)
  230. else
  231. return nil
  232. end
  233. end
  234. ---@return string @ 将数值转化成百分比的字符
  235. function string.numToPercent(value)
  236. -- 首先,将value乘以100
  237. local percentValue = value * 100
  238. -- 然后,使用string.format保留两位小数,并添加%
  239. -- %.2f表示保留两位小数的浮点数
  240. local formattedValue = string.format("%.2f%%", percentValue)
  241. -- 返回格式化后的字符串
  242. return formattedValue
  243. end
  244. ---@return string @ 判断数值是否大于0 大于0返回key拼接value的字符串加上空格 如果是结尾字符则不加空格
  245. function string.joinVar(str, value, ...)
  246. local args = table.pack(...)
  247. if tonumber(value) > 0 then
  248. if (#args > 0 and args[1] == true) then
  249. return str .. ":" .. value
  250. else
  251. return str .. ":" .. value .. " "
  252. end
  253. else
  254. return ""
  255. end
  256. end
  257. ---@return string @ 一般情况下 通过字符返回属性表
  258. function string.getAttrByStr(str)
  259. local dt = {}
  260. local data = string.split(str, "|")
  261. if data then
  262. for _, v in ipairs(data) do
  263. local data2 = string.split(v, "#")
  264. dt[data2[1]] = data2[2]
  265. end
  266. end
  267. return dt
  268. end
  269. ---@return string @ 通过字符返回左右两边数值
  270. function string.LR(str)
  271. local dt = {}
  272. local data = string.split(str, "#")
  273. dt.left = data[1]
  274. dt.right = data[2]
  275. return dt
  276. end
  277. ---@return number @ 将字符串转化为数字,如果失败返回0
  278. function string.tonumber(str)
  279. if type(str) == "number" then
  280. return str
  281. end
  282. if string.isNullOrEmpty(str) or not str:match("^%d+$") then
  283. return 0
  284. end
  285. return tonumber(str)
  286. end
  287. --- @param str string 配置字符串
  288. --- @param sep1 string 内层切割
  289. --- @ param sep2 string 外层切割
  290. --- @return table @ 将字符串转化为map,例如:"道具id#数量|道具id#数量" 转化为 {1=2,3=4}
  291. function string.toIntIntMap(str, sep1, sep2)
  292. local map = {}
  293. string.putIntIntMap(map, str, sep1, sep2)
  294. return map
  295. end
  296. --- 把字符串追加到指定的map里面
  297. --- @param str string 配置字符串
  298. --- @param sep1 string 内层切割
  299. --- @ param sep2 string 外层切割
  300. --- @return table @ 将字符串转化为map,例如:"道具id#数量|道具id#数量" 转化为 {1=2,3=4}
  301. function string.putIntIntMap(map, str, sep1, sep2)
  302. sep1 = sep1 or "#"
  303. sep2 = sep2 or "|"
  304. if not string.isNullOrEmpty(str) then
  305. local data = string.split(str, sep2)
  306. for _, v in ipairs(data) do
  307. local data2 = string.split(v, sep1)
  308. map[tonumber(data2[1])] = tonumber(map[tonumber(data2[1])] or 0) + tonumber(data2[2])
  309. end
  310. end
  311. return map
  312. end
  313. --- @param str string 配置字符串
  314. --- @param sep1 string 内层切割
  315. --- @ param sep2 string 外层切割
  316. --- @return table @ 将字符串转化为map,例如:"道具id#数量|道具id#数量" 转化为 {"1"=2,"3"=4}
  317. function string.toStringIntMap(str, sep1, sep2)
  318. local map = {}
  319. string.putStringIntMap(map, str, sep1, sep2)
  320. return map
  321. end
  322. --- 把字符串追加到指定的map里面
  323. --- @param str string 配置字符串
  324. --- @param sep1 string 内层切割
  325. --- @ param sep2 string 外层切割
  326. --- @return table @ 将字符串转化为map,例如:"道具id#数量|道具id#数量" 转化为 {"1"=2,"3"=4}
  327. function string.putStringIntMap(map, str, sep1, sep2)
  328. sep1 = sep1 or "#"
  329. sep2 = sep2 or "|"
  330. if not string.isNullOrEmpty(str) then
  331. local data = string.split(str, sep2)
  332. for _, v in ipairs(data) do
  333. local data2 = string.split(v, sep1)
  334. map[data2[1]] = (map[data2[1]] or 0) + tonumber(data2[2])
  335. end
  336. end
  337. return map
  338. end
  339. --- @param str string 配置字符串
  340. --- @param sep1 string 内层切割
  341. --- @param sep2 string 外层切割
  342. --- @return table @ 将字符串转化为map,例如:"道具id#数量|道具id#数量" 转化为 {"1"="2","3"="4"}
  343. function string.toStringStringMap(str, sep1, sep2)
  344. local map = {}
  345. string.putStringStringMap(map, str, sep1, sep2)
  346. return map
  347. end
  348. --- 把字符串追加到指定的map里面
  349. --- @param str string 配置字符串
  350. --- @param sep1 string 内层切割
  351. --- @param sep2 string 外层切割
  352. --- @return table @ 将字符串转化为map,例如:"道具id#数量|道具id#数量" 转化为 {"1"="2","3"="4"}
  353. function string.putStringStringMap(map, str, sep1, sep2)
  354. sep1 = sep1 or "#"
  355. sep2 = sep2 or "|"
  356. if not string.isNullOrEmpty(str) then
  357. local data = string.split(str, sep2)
  358. for _, v in ipairs(data) do
  359. local data2 = string.split(v, sep1)
  360. gameDebug.assertNotNil(map[data2[1]], "重复的key", data2[1])
  361. map[data2[1]] = data2[2]
  362. end
  363. end
  364. return map
  365. end
  366. ---根据职业过滤配置,如果不限制职业配置0
  367. ---@param career number 职业,如果不限制职业配置0
  368. ---@param sep1 string 内层切割
  369. ---@param sep2 string 外层切割 例如:"职业#道具id#数量|职业#道具id#数量" 转化为 {1=2,3=4}
  370. function string.toIntIntMap4Career(career, str, sep1, sep2)
  371. local map = {}
  372. string.putIntIntMap4Career(map, career, str, sep1, sep2)
  373. return map
  374. end
  375. ---根据职业过滤配置,把字符串追加到指定的map里面 ,如果不限制职业配置0
  376. ---@param career number 职业,如果不限制职业配置0
  377. ---@param sep1 string 内层切割
  378. ---@param sep2 string 外层切割 例如:"职业#道具id#数量|职业#道具id#数量" 转化为 {1=2,3=4}
  379. function string.putIntIntMap4Career(map, career, str, sep1, sep2)
  380. sep1 = sep1 or "#"
  381. sep2 = sep2 or "|"
  382. if not string.isNullOrEmpty(str) then
  383. local data = string.split(str, sep2)
  384. for _, v in ipairs(data) do
  385. local data2 = string.split(v, sep1)
  386. local cfgCareer = tonumber(data2[1])
  387. if cfgCareer == 0 or cfgCareer == tonumber(career) then
  388. map[tonumber(data2[2])] = tonumber(map[tonumber(data2[2])] or 0) + tonumber(data2[3])
  389. end
  390. end
  391. end
  392. return map
  393. end
  394. function string.equalsIgnoreCase(str1, str2)
  395. return string.lower(str1) == string.lower(str2)
  396. end