参考博客:UTF8字符串在lua的截取和字数统计【转载】

需求

按字面个数来截取子字符串
  1. 函数(字符串, 开始位置, 截取长度)
  2.  
  3. utf8sub("你好1世界哈哈",,) = 1世界哈
  4. utf8sub("1你好1世界哈哈",,) = 你好1世界
  5. utf8sub("你好世界1哈哈",,) = 你好世界1
  6. utf8sub("",,) =
  7. utf8sub("øpø你好pix",,) = 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是对unicode字符集的编码方案。因此其变长编码方式为:

一字节:0*******

两字节:110*****,10******

三字节:1110****,10******,10******

四字节:11110***,10******,10******,10******

五字节:111110**,10******,10******,10******,10******

六字节:1111110*,10******,10******,10******,10******,10******

因此,拿到字节串后,想判断UTF8字符的byte长度,按照上文的规律,只需要获取该字符的首个Byte,根据其值就可以判断出该字符由几个Byte表示。

其代码如下:

  1. local funciton charsize(ch)
  2. if not ch then return
  3. elseif ch >= then return
  4. elseif ch >= and ch < then return
  5. elseif ch >= and ch < then return
  6. elseif ch >= and ch < then return
  7. elseif ch >= and ch < then return
  8. elseif ch < then return
  9. end
  10. end
  1. -- 计算utf8字符串字符数, 各种字符都按一个字符计算
  2. -- 例如utf8len("1你好") => 3
  3. function utf8len(str)
  4. local len =
  5. local aNum = --字母个数
  6. local hNum = --汉字个数
  7. local currentIndex =
  8. while currentIndex <= #str do
  9. local char = string.byte(str, currentIndex)
  10. local cs = charsize(char)
  11. currentIndex = currentIndex + cs
  12. len = len +
  13. if cs == then
  14. aNum = aNum +
  15. elseif cs >= then
  16. hNum = hNum +
  17. end
  18. end
  19. return len, aNum, hNum
  20. end
  1. -- 截取utf8 字符串
  2. -- str: 要截取的字符串
  3. -- startChar: 开始字符下标,从1开始
  4. -- numChars: 要截取的字符长度
  5. function utf8sub(str, startChar, numChars)
  6. local startIndex =
  7. while startChar > do
  8. local char = string.byte(str, startIndex)
  9. startIndex = startIndex + chsize(char)
  10. startChar = startChar -
  11. end
  12.  
  13. local currentIndex = startIndex
  14.  
  15. while numChars > and currentIndex <= #str do
  16. local char = string.byte(str, currentIndex)
  17. currentIndex = currentIndex + chsize(char)
  18. numChars = numChars -
  19. end
  20. return str:sub(startIndex, currentIndex - )
  21. end
  22.  
  23. -- 自测
  24. function test()
  25. -- test utf8len
  26. assert(utf8len("你好1世界哈哈") == )
  27. assert(utf8len("你好世界1哈哈 ") == )
  28. assert(utf8len(" 你好世 界1哈哈") == )
  29. assert(utf8len("") == )
  30. assert(utf8len("øpø你好pix") == )
  31.  
  32. -- test utf8sub
  33. assert(utf8sub("你好1世界哈哈",,) == "好1世界哈")
  34. assert(utf8sub("1你好1世界哈哈",,) == "你好1世界")
  35. assert(utf8sub(" 你好1世界 哈哈",,) == "你好1世界 ")
  36. assert(utf8sub("你好世界1哈哈",,) == "你好世界1")
  37. assert(utf8sub("",,) == "")
  38. assert(utf8sub("øpø你好pix",,) == "pø你好p")
  39.  
  40. print("all test succ")
  41. end
  42.  
  43. test()

Lua截取utf-8编码的中英文混合字符串的更多相关文章

  1. PHP获取中英文混合字符串长度及截取

    1.字符串长度 PHP获取中英文混合字符串长度的实现代码如下,1中文=1位,2英文=1位,可自行修改 /** * PHP获取字符串中英文混合长度 * @param $str string 字符串 *  ...

  2. CSS截取中英文混合字符串长度

    <!doctype html> <html> <head> <meta http-equiv="content-type" content ...

  3. 用C#截取指定长度的中英文混合字符串

    很早以前写过一篇文章(用C#截取指定长度的中英文混合字符串),但是对性能没有测试,有人说我写的这个方法性能有问题,后来想,可能真会有BT之需求要求传入一个几万K甚至几M体积的字符串进来,那将会影响正则 ...

  4. c#的中英文混合字符串截取

    public class StringHelper     {         public static string GetSubString(string str, int len)       ...

  5. c#的中英文混合字符串截取 public static string SubString(string inputString, int byteLength)

    /// <summary>        /// c#的中英文混合字符串截取(区分中英文)        /// </summary>        /// <param ...

  6. c#的中英文混合字符串截取指定长度,startidx从0开始

    //c#的中英文混合字符串截取指定长度,startidx从0开始 by gisoracle@126.com public string getStrLenB(string str, int start ...

  7. C#与JS实现 获取指定字节长度 中英文混合字符串 的方法

    平时在作数据库插入操作时,如果用 INSERT 语句向一个varchar型字段插入内容时,有时会因为插入的内容长度超出规定的长度而报错. 尤其是插入中英文混合字符串时,SQL Server中一般中文要 ...

  8. 中英文混合字符串截取java

    //截取字符串长度(中文2个字节,半个中文显示一个) public String subTextString(String str,int len){ if(str.length()<len/2 ...

  9. 用JS来实现于截取中英文混合字符串方法(转载)

    网站制作过程中,提示层文字超出,需要JS做字符串截取,但是呢,我们常常会烦恼文字中英文混合如何判断,因为我们知道在JS中 string.length这个值是不考虑中英文的,但是计算机对中英文的识别是  ...

随机推荐

  1. Memcache的使用基本介绍

    Memcache学习总结2-Memcache的使用基本介绍 上一次总结中我们已经安装部署好了Memcached,并且把PHP扩展Memcache也安装好了,这一节我们详细学习一下PHP扩展Memcac ...

  2. Mandelbrot和Julia

    概述 mandelbrot julia Mandelbrot 对全体复数z,满足xn+1 =  xn2 + z从x0 = 0起,|x|随n值增加不趋于无穷大,则z属于Mandelbrot集 代码 #i ...

  3. 跟我一起学WCF(1)——MSMQ消息队列

    一.引言 Windows Communication Foundation(WCF)是Microsoft为构建面向服务的应用程序而提供的统一编程模型,该服务模型提供了支持松散耦合和版本管理的序列化功能 ...

  4. 解决代码着色组件SyntaxHighlighter行号显示问题

    SyntaxHighlighter是根据代码中的换行符分配行号的.但是,如果一行代码或者注释比较长,在页面显示时需要分成多行显示,这时行号就对不上了.如下图: 通过下面的css强制不换行,可以避开这个 ...

  5. 2014-3-11 星期二 晴 [卓有成效 master 摸索计划方案]

    今日总结: [汇编]:StudyNew+ReView-->[中]上机,还行,学点新知识 [英语]:Study-->[中]发现这个要变得好啦 [----]:lib [----]:lib--& ...

  6. EF结合三层:三层中数据层父类和业务层父类的使用

    今天我们主要讨论下数据层父类和业务层父类的使用.众所周知,数据层无非就是实现增删改查的方法.无论是哪个实体类,无非就是为了实现增删改查方法,所有我们在三层的DAL层封装了一个BaseDAL类,来做增删 ...

  7. C#课外实践——校园二手平台(心得篇)

    先声明一下,现在回头看一下自己做的小程序,感觉很不怎么地.但是通过这次的实践明白了很多的东西.至于程序实现的什么给你,通过名字就可以猜出来.不过,是客户端的.我想,这应该是我见过的第一个以客户端为模式 ...

  8. Hibernate各种主键生成器策略与配置详解(转载)

    http://www.cnblogs.com/kakafra/archive/2012/09/16/2687569.html 1.assigned 主键由外部程序负责生成,在 save() 之前必须指 ...

  9. Nodejs学习笔记(九)--- 与Redis的交互(mranney/node_redis)入门

    目录 简介和安装 redis简介 redis安装 redis运行 node_redis安装 连接到redis服务器redis.createClient() 认证 client.auth(passwor ...

  10. paip.复制文件 文件操作 api的设计uapi java python php 最佳实践

    paip.复制文件 文件操作 api的设计uapi java python php 最佳实践 =====uapi   copy() =====java的无,要自己写... ====php   copy ...