Lua截取utf-8编码的中英文混合字符串
参考博客:UTF8字符串在lua的截取和字数统计【转载】
需求
按字面个数来截取子字符串
函数(字符串, 开始位置, 截取长度)
utf8sub("你好1世界哈哈",,) = 好1世界哈
utf8sub("1你好1世界哈哈",,) = 你好1世界
utf8sub("你好世界1哈哈",,) = 你好世界1
utf8sub("",,) =
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表示。
其代码如下:
local funciton charsize(ch)
if not ch then return
elseif ch >= then return
elseif ch >= and ch < then return
elseif ch >= and ch < then return
elseif ch >= and ch < then return
elseif ch >= and ch < then return
elseif ch < then return
end
end
-- 计算utf8字符串字符数, 各种字符都按一个字符计算
-- 例如utf8len("1你好") => 3
function utf8len(str)
local len =
local aNum = --字母个数
local hNum = --汉字个数
local currentIndex =
while currentIndex <= #str do
local char = string.byte(str, currentIndex)
local cs = charsize(char)
currentIndex = currentIndex + cs
len = len +
if cs == then
aNum = aNum +
elseif cs >= then
hNum = hNum +
end
end
return len, aNum, hNum
end
-- 截取utf8 字符串
-- str: 要截取的字符串
-- startChar: 开始字符下标,从1开始
-- numChars: 要截取的字符长度
function utf8sub(str, startChar, numChars)
local startIndex =
while startChar > do
local char = string.byte(str, startIndex)
startIndex = startIndex + chsize(char)
startChar = startChar -
end local currentIndex = startIndex while numChars > and currentIndex <= #str do
local char = string.byte(str, currentIndex)
currentIndex = currentIndex + chsize(char)
numChars = numChars -
end
return str:sub(startIndex, currentIndex - )
end -- 自测
function test()
-- test utf8len
assert(utf8len("你好1世界哈哈") == )
assert(utf8len("你好世界1哈哈 ") == )
assert(utf8len(" 你好世 界1哈哈") == )
assert(utf8len("") == )
assert(utf8len("øpø你好pix") == ) -- test utf8sub
assert(utf8sub("你好1世界哈哈",,) == "好1世界哈")
assert(utf8sub("1你好1世界哈哈",,) == "你好1世界")
assert(utf8sub(" 你好1世界 哈哈",,) == "你好1世界 ")
assert(utf8sub("你好世界1哈哈",,) == "你好世界1")
assert(utf8sub("",,) == "")
assert(utf8sub("øpø你好pix",,) == "pø你好p") print("all test succ")
end test()
Lua截取utf-8编码的中英文混合字符串的更多相关文章
- PHP获取中英文混合字符串长度及截取
1.字符串长度 PHP获取中英文混合字符串长度的实现代码如下,1中文=1位,2英文=1位,可自行修改 /** * PHP获取字符串中英文混合长度 * @param $str string 字符串 * ...
- CSS截取中英文混合字符串长度
<!doctype html> <html> <head> <meta http-equiv="content-type" content ...
- 用C#截取指定长度的中英文混合字符串
很早以前写过一篇文章(用C#截取指定长度的中英文混合字符串),但是对性能没有测试,有人说我写的这个方法性能有问题,后来想,可能真会有BT之需求要求传入一个几万K甚至几M体积的字符串进来,那将会影响正则 ...
- c#的中英文混合字符串截取
public class StringHelper { public static string GetSubString(string str, int len) ...
- c#的中英文混合字符串截取 public static string SubString(string inputString, int byteLength)
/// <summary> /// c#的中英文混合字符串截取(区分中英文) /// </summary> /// <param ...
- c#的中英文混合字符串截取指定长度,startidx从0开始
//c#的中英文混合字符串截取指定长度,startidx从0开始 by gisoracle@126.com public string getStrLenB(string str, int start ...
- C#与JS实现 获取指定字节长度 中英文混合字符串 的方法
平时在作数据库插入操作时,如果用 INSERT 语句向一个varchar型字段插入内容时,有时会因为插入的内容长度超出规定的长度而报错. 尤其是插入中英文混合字符串时,SQL Server中一般中文要 ...
- 中英文混合字符串截取java
//截取字符串长度(中文2个字节,半个中文显示一个) public String subTextString(String str,int len){ if(str.length()<len/2 ...
- 用JS来实现于截取中英文混合字符串方法(转载)
网站制作过程中,提示层文字超出,需要JS做字符串截取,但是呢,我们常常会烦恼文字中英文混合如何判断,因为我们知道在JS中 string.length这个值是不考虑中英文的,但是计算机对中英文的识别是 ...
随机推荐
- maven异常
1.There are test failures pom中加入: <build> <plugins> <plugin> <groupId>org.ap ...
- mysql增加普通用户后无法登陆问题的解决方法
解决方法: 增加普通用户后,执行: mysql> use mysql mysql> delete from user where user=''; mysql> flush priv ...
- Swift 3.0 令人兴奋,但Objective-C也有小改进--Objective-C的类属性
由于Swift 3.0 出了太多令人兴奋的新特性,人们很容易忽略 Objective-C中的小改动.或许你会觉得苹果提及Objective-C 很可能是为了提高和Swift互操作性(译者注:互操作性主 ...
- node-webkit教程(16)调试typescript
原文链接:node-webkit教程(16)调试typescript 本文所讲的内容同样适用于chrome浏览器. 在chrome的开发人员工具的配置项中,有一个sourcemap的选项,用来配置ja ...
- SQL SERVER--单回话下的死锁
很多时候,死锁由两个或多个会话请求其他Session持有的锁而同时又持有其他Session,但也有一些特殊的死锁仅由单个Session锁触发,今天看到一篇相关的文章,搬运过来与各位共享! 引发死锁的代 ...
- 04-Vue入门系列之Vue事件处理
4.1. 监听事件的Vue处理 Vue提供了协助我们为标签绑定时间的方法,当然我们可以直接用dom原生的方式去绑定事件.Vue提供的指令进行绑定也是非常方便,而且能让ViewModel更简洁,逻辑更彻 ...
- JAVA通过XPath解析XML性能比较(原创)
(转载请标明原文地址) 最近在做一个小项目,使用到XML文件解析技术,通过对该技术的了解和使用,总结了以下内容. 1 XML文件解析的4种方法 通常解析XML文件有四种经典的方法.基本的解析方式有两种 ...
- 常用dom对象
DOM:文档对象模型 --树模型 文档:标签文档,对象:文档中每个元素对象,模型:抽象化的东西 一:window: window.shuxing; 属性(值或者子对象): opener:打开当前窗口的 ...
- XML的简单学习
推荐入门级学习XML网址W3c http://www.w3school.com.cn/xml/xml_intro.asp 1: XML 指可扩展标记语言 XML 被设计用来传输和存储数据 ...
- Leetcode 165 Compare Version Numbers
题意:比较版本号的大小 有点变态,容易犯错 本质是字符串的比较,请注意他的版本号的小数点不知1个,有的会出现01.0.01这样的变态版本号 class Solution { public: int c ...