文档章节

lua 截取字符,以及取字符个数(非字符串长度)

赵占涛
 赵占涛
发布于 2016/10/14 16:53
字数 640
阅读 373
收藏 1

需求

按字面个数来截取

函数(字符串, 开始位置, 截取长度)

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()

本文转载自:http://www.zhaoxiaodan.com/%E5%85%B6%E4%BB%96/UTF8%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%9C%A8lua%E7%9A%84%E

赵占涛

赵占涛

粉丝 54
博文 26
码字总数 4416
作品 3
海淀
私信 提问
Oracle中的substr()函数 详解及应用-收集

1)substr函数格式 (俗称:字符截取函数)   格式1: substr(string string, int a, int b);   格式2:substr(string string, int a) ; 解释: 格式1 1、string 需要截取的字符串 2、a 截...

诺岚
2018/03/20
0
0
linux下变量使用和扩展

变量定义 格式:变量名=变量值 注意:1、’‘="两边不能有空格 2、变量值,linux都会认为是字符串,如果有字符有空格,需要用双引号或单引号括起 3、变量值,双引号括起,会解释变量;而单引...

沙米笔记
2016/08/26
17
0
Oracle常用单行函数(原创)

前言: 想把单行函数进行一个比较全面的总结,并分享给有需要的人,有不明之处还请多多指教。 SQL函数:Oracle的内置函数,包括了单行函数和多行函数,本文重点讲解单行函数。单行函数又可以...

矜持先森么么哒
2018/08/06
0
0
shell脚本中字符串截取的常用用法

转载自:http://lidao.blog.51cto.com/3388056/1949831 假设有变量 1. # 号截取,删除左边字符,保留右边字符。 变量: var=http://www.oldboyedu.com/123.htmecho ${var#*//}其中 var 是变量...

qq441009395
2018/06/26
0
0
Mysql字符串截取总结:left()、right()、substring()、substring_index()

同步首发:http://www.yuanrengu.com/index.php/20171226.html 在实际的项目开发中有时会有对数据库某字段截取部分的需求,这种场景有时直接通过数据库操作来实现比通过代码实现要更方便快捷...

夏雪冬日
2017/12/26
0
0

没有更多内容

加载失败,请刷新页面

加载更多

C 语言 二级指针操作文件 柔性数组使用

#include <stdio.h>#include <stdlib.h>#include <string.h>typedef struct _info* pInfo;struct _info{int line;int len;char data[0];}info;int getFil......

小张525
25分钟前
0
0
中介者模式

https://blog.csdn.net/jason0539/article/details/45216585

南桥北木
25分钟前
0
0
抽离css以及公共js

分离css 分离css:为何要把 CSS 文件分离出来,而不是直接一起打包在 JS 中。最主要的原因是我们希望更好地利用缓存。 extract-text-webpack-plugin > 1. 假设我们原本页面的静态资源都打包成...

莫西摩西
58分钟前
1
0
Jenkins的配置从节点中默认没有Launch agent via Java Web Start,该如何配置使用

Jenkins的配置从节点中默认没有Launch agent via Java Web Start,如下图所示,而这种启动方式在Windows上是最方便的。 如何设置才能让出来呢? 1:打开"系统管理"——"Configure Global Sec...

shzwork
今天
2
0
BAT面试必问HashMap源码分析

HashMap 简介 HashMap 主要用来存放键值对,它基于哈希表的Map接口实现,是常用的Java集合之一。 JDK1.8 之前 HashMap 由 数组+链表 组成的,数组是 HashMap 的主体,链表则是主要为了解决哈...

别打我会飞
今天
17
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部