zoukankan      html  css  js  c++  java
  • UTF8字符串在lua的截取和字数统计【转载】

    转载自:GitHub:/pangliang.github.com

    需求

    按字面个数来截取
    函数(字符串, 开始位置, 截取长度)
    
    utf8sub("你好1世界哈哈",2,5)    =    好1世界哈
    utf8sub("1你好1世界哈哈",2,5)    =    你好1世界
    utf8sub("你好世界1哈哈",1,5)    =    你好世界1
    utf8sub("12345678",3,5)    =    34567
    utf8sub("øpø你好pix",2,5)    =    pø你好p

    错误方法

    网上找了一些算法, 都不太正确; 要么就是乱码, 要么就是只考虑了4 byte 中文的情况, 不够全面

    1. string.sub(s,1,截取长度*4)

      网上很多直接使用"`""string.sub(s,1,截取长度*4)`"是肯定不对的, 因为如果中英文混合的字符串, 例如`你好1世界`的字符长度分别是`4,4,1,4,4`, 如果截取4个字, 4*4=4+4+1+4+3, 那`世界`的`界`字将会被取前3个byte, 就会出现乱码

    2. if byte>128 then index = index + 4

    问题关键

    1. utf8字符是变长字符

    2. 字符长度有规律

    UTF-8字符规律

    字符串的首个byte表示了该utf8字符的长度

    0xxxxxxx - 1 byte

    110yxxxx - 192, 2 byte

    1110yyyy - 225, 3 byte

    11110zzz - 240, 4 byte

    正确算法

     1 --
     2 -- lua
     3 -- 判断utf8字符byte长度
     4 -- 0xxxxxxx - 1 byte
     5 -- 110yxxxx - 192, 2 byte
     6 -- 1110yyyy - 225, 3 byte
     7 -- 11110zzz - 240, 4 byte
     8 local function chsize(char)
     9     if not char then
    10         print("not char")
    11         return 0
    12     elseif char > 240 then
    13         return 4
    14     elseif char > 225 then
    15         return 3
    16     elseif char > 192 then
    17         return 2
    18     else
    19         return 1
    20     end
    21 end
    22 
    23 -- 计算utf8字符串字符数, 各种字符都按一个字符计算
    24 -- 例如utf8len("1你好") => 3
    25 function utf8len(str)
    26     local len = 0
    27     local currentIndex = 1
    28     while currentIndex <= #str do
    29         local char = string.byte(str, currentIndex)
    30         currentIndex = currentIndex + chsize(char)
    31         len = len +1
    32     end
    33     return len
    34 end
    35 
    36 -- 截取utf8 字符串
    37 -- str:            要截取的字符串
    38 -- startChar:    开始字符下标,从1开始
    39 -- numChars:    要截取的字符长度
    40 function utf8sub(str, startChar, numChars)
    41     local startIndex = 1
    42     while startChar > 1 do
    43         local char = string.byte(str, startIndex)
    44         startIndex = startIndex + chsize(char)
    45         startChar = startChar - 1
    46     end
    47 
    48     local currentIndex = startIndex
    49 
    50     while numChars > 0 and currentIndex <= #str do
    51         local char = string.byte(str, currentIndex)
    52         currentIndex = currentIndex + chsize(char)
    53         numChars = numChars -1
    54     end
    55     return str:sub(startIndex, currentIndex - 1)
    56 end
    57 
    58 -- 自测
    59 function test()
    60     -- test utf8len
    61     assert(utf8len("你好1世界哈哈") == 7)
    62     assert(utf8len("你好世界1哈哈 ") == 8)
    63     assert(utf8len(" 你好世 界1哈哈") == 9)
    64     assert(utf8len("12345678") == 8)
    65     assert(utf8len("øpø你好pix") == 8)
    66 
    67     -- test utf8sub
    68     assert(utf8sub("你好1世界哈哈",2,5) == "好1世界哈")
    69     assert(utf8sub("1你好1世界哈哈",2,5) == "你好1世界")
    70     assert(utf8sub(" 你好1世界 哈哈",2,6) == "你好1世界 ")
    71     assert(utf8sub("你好世界1哈哈",1,5) == "你好世界1")
    72     assert(utf8sub("12345678",3,5) == "34567")
    73     assert(utf8sub("øpø你好pix",2,5) == "pø你好p")
    74 
    75     print("all test succ")
    76 end
    77 
    78 test()
  • 相关阅读:
    分别针对Customers表与Order表的通用查询操作
    类的继承
    kubernetes service 原理解析
    k8s生命周期-钩子函数
    深入理解Pod-初始化容器
    为 Pod 或容器配置安全性上下文
    Docker四种网络模式
    python中__new__方法详解及使用
    浅析python析构函数
    k8s中的网络
  • 原文地址:https://www.cnblogs.com/bicker/p/5282733.html
Copyright © 2011-2022 走看看