zoukankan      html  css  js  c++  java
  • lua 截取字符,以及取字符个数(非字符串长度)

    需求

    按字面个数来截取

    函数(字符串, 开始位置, 截取长度)
    
    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
    

    各种正确算法

    -- 判断utf8字符byte长度
    -- 0xxxxxxx - 1 byte
    -- 110yxxxx - 192, 2 byte
    -- 1110yyyy - 225, 3 byte
    -- 11110zzz - 240, 4 byte
    local function chsize(char)
        if not char then
            print("not char")
            return 0
        elseif char > 240 then
            return 4
        elseif char > 225 then
            return 3
        elseif char > 192 then
            return 2
        else
            return 1
        end
    end
    
    -- 计算utf8字符串字符数, 各种字符都按一个字符计算
    -- 例如utf8len("1你好") => 3
    function utf8len(str)
        local len = 0
        local currentIndex = 1
        while currentIndex <= #str do
            local char = string.byte(str, currentIndex)
            currentIndex = currentIndex + chsize(char)
            len = len +1
        end
        return len
    end
    
    -- 截取utf8 字符串
    -- str:            要截取的字符串
    -- startChar:    开始字符下标,从1开始
    -- numChars:    要截取的字符长度
    function utf8sub(str, startChar, numChars)
        local startIndex = 1
        while startChar > 1 do
            local char = string.byte(str, startIndex)
            startIndex = startIndex + chsize(char)
            startChar = startChar - 1
        end
    
        local currentIndex = startIndex
    
        while numChars > 0 and currentIndex <= #str do
            local char = string.byte(str, currentIndex)
            currentIndex = currentIndex + chsize(char)
            numChars = numChars -1
        end
        return str:sub(startIndex, currentIndex - 1)
    end
    
    -- 自测
    function test()
        -- test utf8len
        assert(utf8len("你好1世界哈哈") == 7)
        assert(utf8len("你好世界1哈哈 ") == 8)
        assert(utf8len(" 你好世 界1哈哈") == 9)
        assert(utf8len("12345678") == 8)
        assert(utf8len("øpø你好pix") == 8)
    
        -- test utf8sub
        assert(utf8sub("你好1世界哈哈",2,5) == "好1世界哈")
        assert(utf8sub("1你好1世界哈哈",2,5) == "你好1世界")
        assert(utf8sub(" 你好1世界 哈哈",2,6) == "你好1世界 ")
        assert(utf8sub("你好世界1哈哈",1,5) == "你好世界1")
        assert(utf8sub("12345678",3,5) == "34567")
        assert(utf8sub("øpø你好pix",2,5) == "pø你好p")
    
        print("all test succ")
    end
    
    test()

    https://my.oschina.net/u/930967/blog/758653

  • 相关阅读:
    SQL-Duplicate Emails
    c#创建可比较对象
    c#扩展方法
    C#Lambda和委托
    C#集合
    c#显示实现接口和隐式实现的区别
    bs同时上传文件以及文件信息
    sql查询数据库中所有 ,数据为空的表
    sql查询所有表名和描述
    MES数据采集模块小结
  • 原文地址:https://www.cnblogs.com/7qin/p/13511309.html
Copyright © 2011-2022 走看看