Lua 截取字符串(截取utf-8格式字符串)
对utf-8完全没概念的可以看看我上一篇随笔:简单说说utf-8编码格式
另外,还要知道string.sub 和 string.byte 的用法。


先上完整代码:
local  StringHelper = {}
--[[
utf-8编码规则
单字节 - 0起头
   1字节  0xxxxxxx   0 - 127
多字节 - 第一个字节n个1加1个0起头
   2 字节 110xxxxx   192 - 223
   3 字节 1110xxxx   224 - 239
   4 字节 11110xxx   240 - 247
可能有1-4个字节
--]]
function StringHelper.GetBytes(char)
   if not char then
      return
   end
   local code = string.byte(char)
   if code <  then
      return
   elseif code <=  then
      return
   elseif code <=  then
      return
   elseif code <=  then
      return
   else
      -- 讲道理不会走到这里^_^
      return
   end
end
function StringHelper.Sub(str, startIndex, endIndex)
   local tempStr = str
   local byteStart =  -- string.sub截取的开始位置
   local byteEnd = - -- string.sub截取的结束位置
   local index =   -- 字符记数
   local bytes =   -- 字符的字节记数
   startIndex = math.max(startIndex, )
   endIndex = endIndex or -
   while string.len(tempStr) >  do
      if index == startIndex -  then
         byteStart = bytes+;
      elseif index == endIndex then
         byteEnd = bytes;
         break;
      end
      bytes = bytes + StringHelper.GetBytes(tempStr)
      tempStr = string.sub(str, bytes+)
      index = index +
   end
   return string.sub(str, byteStart, byteEnd)
end
基本思路:
之所以要自己写一个截取函数,是因为lua的库函数string.sub实际是字节的截取函数。
uft-8编码格式中,大部分中文是3个字节表示的,数字和字母等是一个字节的,还有某些国家的语言是2字节的,直接用string.sub就可能截出乱码来,因为不确定要截多少个字节。
所以,
定义一个GetBytes函数,获取字符的字节数(根据首个字节的高位标记,判断是几字节的字符)
然后不断后移,记录字节数和字符数。

如上图,假设要取字符3-4,那么应该从第3个字符的第一个字节取到第4个字最后一个字节
即:
当前字符数为截取的起始字符(startIndex)前一个位置时,说明从下一个字节开始截取字符串 即 index == startIndex - 1 时 byteStart = bytes+1
当前字符数为截取的终止字符(endIndex)时,说明要截取的字符串到此为止 即 index == endIndex 时 byteEnd = bytes
用 string.sub(str, byteStart, byteEnd) 就能截取byteStart 到 byteEnd 的字节
测试代码:
str = "中1文*a字符串勉強します";
print(StringHelper.Sub(str, 3, 4))
print(StringHelper.Sub(str, , ))
print(StringHelper.Sub(str, ))
print(StringHelper.Sub(str, , ))
测试结果:

Lua 截取字符串(截取utf-8格式字符串)的更多相关文章
- 标准 DateTime 格式字符串
		
标准 DateTime 格式字符串 MSDN 标准 DateTime 格式字符串包含一个标准 DateTime 格式说明符字符,该字符表示自定义 DateTime 格式字符串.格式字符串最终定义由格式 ...
 - java中驼峰与下横线格式字符串互转算法
		
public static final char UNDERLINE = '_'; /** * 驼峰格式字符串转换为下划线格式字符串 * * @param param * @return */ pub ...
 - web 前端 常见操作  将时间戳转成日期格式  字符串截取  使用mui制作选项卡
		
1.将时间戳转成日期格式: //第一种 function getLocalTime(nS) { return new Date(parseInt(nS) * 1000).toLocaleString( ...
 - Linux字符串截取和处理命令 cut、printf、awk、sed、sort、wc
		
1. cut [选项] 文件名 -f 列号 #提取第几列(分隔符默认为\t) -d 分隔符 #指定分隔符 例如:cut -f 2 a.txt #截取文件a.txt内容的第二列(列号从1开始) cu ...
 - lr_save_var字符串截取总结
		
函数作用: 将一个变化长度的字符串保存到parameter中. 用法实例: 此处讲解函数: Action() { web_save_timestamp_param("tStamp&q ...
 - Mysql字符串截取函数SUBSTRING的用法说明
		
感觉上MySQL的字符串函数截取字符,比用程序截取(如PHP或JAVA)来得强大,所以在这里做一个记录,希望对大家有用. 函数: 1.从左开始截取字符串 left(str, length) 说明:le ...
 - shell字符串操作之cut---实现字符串截取
		
shell中(字符串截取) cut是以每一行为一个处理对象的,这种机制和sed是一样的.(关于sed的入门文章将在近期发布) 2 cut一般以什么为依据呢? 也就是说,我怎么告诉cut我想定位到的剪切 ...
 - 关于Java和JavaScript对字符串截取处理的总结
		
在JavaWeb开发中,经常需要对字符串进行处理,包括Java语言和JS语言,总是容易弄混淆,这里简单对比一下两种语言对于字符串截取方法. 一.先看Java public class StringDe ...
 - thinkPHP内置字符串截取msubstr函数用法详解
		
作者:陈达辉 字体:[增加 减小] 类型:转载 时间:2016-11-15 我要评论 这篇文章主要介绍了thinkPHP内置字符串截取函数用法,结合实例形式分析了thinkPHP内置的字符串截取函数功 ...
 - MySQL 字符串截取SUBSTRING()函数
		
MySQL 字符串截取相关函数: 1.从左开始截取字符串 left(str, length) 说明:left(被截取字段,截取长度) 例: select left(content,200) as ab ...
 
随机推荐
- django快速实现完整登录系统,把登陆注册串在一起并增加cookie(六)
			
1.使用之前创建的项目和应用 mysite3 account 2.使用之前的数据库构造 class User(models.Model): username=models.CharField(max ...
 - pdnovel 看书 读书 听书
			
pdnovel剖度小说是discuz的阅读插件,这里分享一下阅读的一些技巧. 看书 点击或手机输入 http://txt.xlongwei.com 即可进入阅读首页,内容分书book.卷volume. ...
 - Redis 4.x RCE 复现学习
			
攻击场景: 能够访问远程redis的端口(直接访问或者SSRF) 对redis服务器可以访问到的另一台服务器有控制权 实际上就是通过主从特性来 同步传输数据,同时利用模块加载来加载恶意的用来进行命令执 ...
 - 来谈谈MySQL的临时表,到底是个什么东西,以及怎么样产生的
			
介绍临时表之前,我们首先来看这么一句语句: CREATE TABLE `words` ( `id` ) NOT NULL AUTO_INCREMENT, `word` ) DEFAULT NULL, ...
 - python获得坐标系信息
			
# -*- coding: cp936 -*- ############################################################# import arcpy i ...
 - POCO C++库笔记 【1.Foundation基础库的结构】
			
Foundation库是POCO的基础库,提供了一些C++编程中常用的功能的抽象封装,主要由以下这些部分组成: Core -- 这部分除了建立跨平台库的基础头文件外,最有意义的部分是分装了原子计数的 ...
 - JavaScript中原型链存在的问题解析
			
我们知道使用原型链实现继承是一个goodway:)看个原型链继承的例子. function A () { this.abc = 44; } A.prototype.getAbc = function ...
 - Ubuntu14.04+安卓系统4.3+JDK6编译源码
			
本博客主要参照: https://www.jianshu.com/p/ecb9c132030f https://blog.csdn.net/gobitan/article/details/243674 ...
 - Hadoop、spark
			
http://blog.csdn.net/u011204847/article/details/51355272
 - keepalived+LVS-DR集群
			
一.Keepalived介绍 keepalived 是一个类似于 layer3, 4 & 5 交换机制的软件,也就是我们平时说的第 3 层.第 4 层和第 5层交换. Keepalived 的 ...