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这个值是不考虑中英文的,但是计算机对中英文的识别是 ...
随机推荐
- Fragment的基本用法
一.Fragment主要用到的API: 1.Fragment 类-----用来创建碎片 2.FragmentManager 类 ----为管理Activity中Fragment,用于Activity与 ...
- MVVM了解
了解WPF要有两年,零零碎碎也做了几个项目,之前面试的时候面试官必问对MVVM的了解. 其实不太了解,只是做项目的时候一直采用这种模式,Model-View-ViewModel.以下是我在了解过程中的 ...
- Ajax调用WebService
前台代码: <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1 ...
- 使用javamail发送邮件错误:550 5.7.1 Unable to relay
这两天由于客户的邮件服务器迁移,使用了NTLM的验证方式.系统使用javamailAPI进行发送邮件时,发现只能对内部邮箱进行发送,对外部邮箱进行发送的时候,报下图错误: 后面发现是由于系统的java ...
- sql trunc()的使用
1.TRUNC(for dates)TRUNC函数为指定元素而截去的日期值.其具体的语法格式如下:TRUNC(date[,fmt])其中:date 一个日期值fmt 日期格式,该日期将由指定的元素格式 ...
- windows上自动设置java环境变量的脚本
近期打算学习安卓开发,于是乎要准备java开发环境,安装好jdk后,就要设置java环境变量,java环境变量要设置JAVA_HOME,Path,CLASSPATH三个值,每次配置查百度复制粘贴都很麻 ...
- Unity3D——键盘控制移动
public float speed = 6f; Vector3 movement; void FixedUpdate () { float h = Input.GetAxisRaw("Ho ...
- 读《你必须知道的.NET》继承本质论 Bird bird=new Chicken()
我们创建如下的三层继承层次类. public abstract class Animal { public abstract void ShowType(); } public class Bird ...
- Nginx学习笔记(九) 配置文件详细说明
配置文件详细说明 工作了几个月要开始做一些后台开发,免不了接触nginx,以前一般只是简单的使用,更多的分析内部模块的具体实现,为了部署需要进一步掌握配置方法. 全局配置信息 #nginx worke ...
- 字符串匹配算法之BF(Brute-Force)算法
BF(Brute-Force)算法 蛮力搜索,比较简单的一种字符串匹配算法,在处理简单的数据时候就可以用这种算法,完全匹配,就是速度慢啊. 基本思想 从目标串s 的第一个字符起和模式串t的第一个字符进 ...