Lua 数据类型 —— 字符串

news2024/12/24 22:05:19

一、字符串

Lua 使用 八个比特位来存储 字符。(一个字节 = 八个比特位)

Lua 最好使用 UTF-8 编码。

字符串是不可变值,和 java 和 kotlin 相似,修改其中某一个字符,都是创建一个新的字符串。

Lua 对字符串会进行自动内存管理,会自动进行字符串的分配和释放。

二、函数

1、获取字符串长度

使用 # 获取字符串所占字节数,编码不同可能会有不同结果

a = "Jiang 澎涌"
print(a .. " size: " .. #a) --> Jiang 澎涌 size: 12

2、字符串拼接

使用 .. 字符串拼接,如果操作数中存在数值,则会先将数值转为字符串

3、转义字符

C 风格转义字符:

符号描述
\a响铃
\b退格
\f换页
\n换行
\r回车
\t水平制表符
\v垂直制表符
\反斜杠
"双引号
单引号

转义序列

\ddd(d 是十进制数) 、 \xhh(h 是十六进制数)

使用的是 ASCII 编码

--- 两种写法一样的表示 (A == '0x41' ,\n == '\0' ,1 == '\049')
print("ALO\n123\"")         --> ALO 换行 123"
print('\x41LO\10\04923"')   --> AL0 换行 123"

Lua 5.3 开始,可以使用转义序列 \u{h....h} 来声明 UTF-8 字符。 h 代表十六进制

print("\u{3b1} \u{3b2} \u{3b3}") -->α β γ

转义的使用

在某些系统下,‘\r\n’ 会被归一化为 ‘\n’ , 这个时候可以使用十进制数值或十六进制数值来表示。

可以借助一些网上工具进行获取相应编码,https://tool.chinaz.com/tools/unicode.aspx

三、多行字符串

多行字符串更多用于文本,内容中的转义序列不会被转义,并且第一个字符是换行符的话,则会被忽略。

multiLines = [[
    Hello world.
    Jiang Pengyong.
]]
print(multiLines)

为了应对文本中可能含有 [[]] 字符,所以可以使用 [===[ 在两个 [ 中夹杂 0-n 个等号,相对应的终止也要同样多的等号夹杂在 ] 中。

superMultiLines = [=====[
    Hello world
    Jiang Pengyong
    --[[
    ]]
]=====]
print(superMultiLines)

可以通过 \z 去除字符串中的空白字符,直到下一个非空白字符串

data = "123\z
        456"
print(data)     --> 123456

四、强制类型转换

1、字符串转数值

字符串运算操作

所有针对字符串的算数操作都会尝试将字符串转为数值

print("10" + "1")           --> 11
print("10" + 1)             --> 11
print(10 + "1")             --> 11
print(10 + 1)               --> 11
print("10.0" + "1")         -->  11.0
print("\"10\" + 1 ===>>", "10" + 1, math.type("10" + 1))    --> "10" + 1 ===>>	11	integer

值得注意的是比较操作,字符串不会进行转换成数值

  • 不能将数值和字符串进行比较,否则异常 attempt to compare number with string
  • 字符串之间比较的是字符
print("10" == 10)   --> false
print("10" < 11)    -- attempt to compare string with number
print(10 < "11")    -- attempt to compare string with number
print("10" < "11")   --> true
print(10 < 11)       --> true

tonumber 转换

可以使用 tonumber 函数,将字符串转为数值,Lua 扫描器会判定最终是整型值还是浮点类型值

转换符合 “数值类型” 中的通用规则

print(tonumber("   -3  "))          --> -3
print(tonumber("   10e2  "))        --> 1000.0
print(tonumber("   10e  "))         --> nil
print(tonumber("   0x1.3p-4  "))    --> 0.07421875

tonumber 还可以选择想转的进制,可选 [2,36] 进制,默认为十进制

print(tonumber("100101", 2))    --> 37
print(tonumber("fff", 16))      --> 4095
print(tonumber("-ZZ", 36))      --> -1295
print(tonumber("987", 8))       --> nil

如果转不成功,则返回 nil

2、数值转字符串 tostring

将数值转连接使用 .. 要记得数值和连接符隔开,否则会被当成小数点

print(10 .. 1)      --> 101

可以使用 tostring 将数值转为字符串

print(tostring(10) == "10")  --> true

五、字符串标准库

函数描述
string.len(s)获取字符串 s 的长度
string.rep(s, n)将字符串 s 重复 n 次
string.reverse(s)字符串翻转
string.lower(s)将所有的大写字母转为小写字母
string.upper(s)将所有的小写字母转为大写字母
string.sub(s, i, j)从字符串 s 中提取第 i 个到第 j 个字符,包含 i 和 j ,就是 [i, j]
string.char(i …)可以传入零个或多个整数,返回每个整数转换成对应的字符,最后连接为字符串
string.byte(s, i = 0)返回字符串 s 中第 i 个字符的数值
string.byte(s, i, j)返回字符串 s 中 i 到 j之间( [i, j] )的字符数值
string.format(s, …)进行字符串格式化和将数值输出为字符串
string.find(s, s1)在字符串 s 中,寻找字符串 s1 的下标,会有两个返回值,一个是起始下标一个是终止下标, 查询不到则返回 nil
string.gsub(s, s1, replace)在字符串 s 中,寻找到字符串 s1 ,并用 replace 字符串进行替换,会返回两个值,一个值替换完的字符串,一个是替换的次数(即使没替换成功,也会有两个返回值)

string.sub(s, i, j) 的 i 和 j 可以为负数,则从后面开始计算,-1 代表最后一位

name = "Jiang Pengyong"
-- string.len(name) 等同于 #name , 等同于 name:len()
print(string.len(name))     --> 14
print(#name)                --> 14
print(name:len())           --> 14
print(string.rep("jiang", 5))   --> jiangjiangjiangjiangjiang
print(string.reverse(name))     --> gnoygneP gnaiJ
print(string.upper(name))       --> JIANG PENGYONG
print(string.lower(name))       --> jiang pengyong
-- 字符串的索引是从 1 开始,裁剪的包括两个下标 [i, j]
print(string.sub(name, 1, 5))       --> Jiang
-- 负数表示从后往前计算,-1 表示最后一个字符
print(string.sub(name, 1, -2))      --> Jiang Pengyon
print(string.sub(name, 11, -1))     --> yong
print(string.char(97))              --> a
print(string.char(97, 98, 99))      --> abc
-- byte 如果没有填第二个参数,则直接使用第一个字符
-- 索引也是从 1 开始
print(string.byte("abc"))           --> 97
print(string.byte("abc", 2))        --> 98
print(string.byte("abc", -1))       --> 99
print(string.byte("abc", 1, -1))    --> 97	98	99
-- 创建一个包含所有字符的表 [1, -1] ,只是要控制好大小,不能超过 1 M
local t = { string.byte(name, 1, -1) }
print("table: " .. #t)
for i = 1, #t do
    print(i .. "-->" .. t[i])
end

--> table: 14
--> 1-->74
--> 2-->105
--> 3-->97
--> 4-->110
--> 5-->103
--> 6-->32
--> 7-->80
--> 8-->101
--> 9-->110
--> 10-->103
--> 11-->121
--> 12-->111
--> 13-->110
--> 14-->103
-- find 查询到会返回两个数 开始位置 结束位置, 如果找不到则返回 nil
print(string.find(name, "Jiang"))      --> 1	5
print(string.find(name, "jiang"))       --> nil
-- 进行替换字符,会返回两个 替换的字符 和 替换的个数
print(string.gsub(name, "j", "."))      --> Jiang Pengyong	0       (未查询到)
print(string.gsub(name, "ong", "."))    --> Jiang Pengy.	1       (查询到一次)
print(string.gsub(name, "g", "."))      --> Jian. Pen.yon.	3       (查询到多次)

string.format

因为 Lua 是通过调用 C 语言标准库来完成实际工作,所以格式化和 C 一样,可以使用和 C 一样的操作。

  • d 代表十进制整数
  • x 代表十六进制整数 (a-f 小写)
  • X 代表十六进制整数 (a-f 大写)
  • f 代表浮点数
  • s 代表字符串

可以在 % 和 字母间增加数字,当格式化的内容长度不够数字是,会用“ ”(空格)补足,如果增加 0 则会用 0 补足空间。

print(string.format("pi = %.4f", math.pi))          --> pi = 3.1416
-- 如果不使用 0 ,则默认使用空格
print(string.format("%02d/%02d/%04d", 4, 5, 2022))  --> 04/05/2022
print(string.format("%2d/%2d/%4d", 4, 5, 2022))     -->  4/ 5/2022
print(string.format("%x", 15))                      --> f
print(string.format("%X", 15))                      --> F
print(string.format("%15s", "jiang"))               -->           jiang

六、Unicode 编码

5.3 引入了用于操作 UTF8 的 Unicode 字符串标准库。

UTF8 使用变长的多个字节来编码一个 Unicode 字符。

string 函数对 utf8 的使用

string 的有些函数并不适合处理 utf8 ,例如这些:reverse , upper , lower , byte , char

chineseName = "江澎涌"
print(string.reverse(chineseName))  --> ��掾柱�
print(string.upper(chineseName))    --> 江澎涌
print(string.lower(chineseName))    --> 江澎涌
print(string.byte(chineseName))     --> 230
print(string.char(chineseName))     -- bad argument #1 to 'char' (number expected, got string)

format , rep , len , sub 适用 utf8 的字符串

format 中不能继续使用 %c 来进行展示字符串

值得注意: lensub 的索引是以字节为单位,不是以字符为单位。例如这里的 “江” 是 3 个字节,所以 len 会返回 9 ,sub 的截取其实下标为 2 时,则出现乱码。

print(string.format("名字: %s", chineseName))  --> 名字: 江澎涌
print(string.rep(chineseName, 5))               --> 江澎涌江澎涌江澎涌江澎涌江澎涌
print(string.len(chineseName))                  --> 9
print(string.sub(chineseName, 2, -1))           --> ��澎涌

urf8 标准库

函数描述
utf8.len(s)返回指定字符串中 UTF8 字符的个数。如果该函数发现字符串中包含有无效的字符序列,则会返回两个值,第一个值为 false,第二个值为第一个无效字节的位置
utf8.char(int …)在 utf8 环境下,等价于 string.char
utf8.codepoint(s, i, j)在 utf8 环境下,等价于 string.byte ( i 和 j 是字节,不是字符)
utf8.offset(s, i)获取 s 字符串中,第 i 个字符的以字节索引
utf8.codes(s)用于遍历 utf8 字符串中的每一个字符,每次遍历都会返回两个值,一个是字节索引,一个是编码

utf8 库中索引大多是字节为单位,而非字符。可以用 offset 把字符位置转为字节位置

utf8 库的索引一样可以使用负数,一样是从后往前的意思

chineseName = "江澎涌"

print("utf8.len: ", utf8.len(chineseName), "string.len", string.len(chineseName))       --> utf8.len: 	3	string.len	9
print(utf8.len("ab\x93"))                                                               --> nil	3

print("codepoint:", utf8.codepoint("澎"))  --> codepoint:	28558
print("char", utf8.char(28558))             --> char	澎

print(utf8.offset(chineseName, 2))                              --> 4
print(string.sub(chineseName, utf8.offset(chineseName, 2)))     --> 澎涌

-- codes 遍历 utf8 字符串中的每一个字符
for i, j in utf8.codes(chineseName) do
    print(i .. "-->" .. j .. "-->" .. utf8.char(j))
end

--> 1-->27743-->江
--> 4-->28558-->澎
--> 7-->28044-->涌

七、写在最后

Lua 项目地址:Github传送门 (如果对你有所帮助或喜欢的话,赏个star吧,码字不易,请多多支持)

公众号搜索 “江澎涌” 可以第一时间获取到后续文章

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/860848.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python进阶(二)

前言&#xff1a;本篇博客主要记录Python进程的创建、进程间的通信、进程池的使用、线程的创建、多线程的执行、同步和互斥、协程的创建和应用。 目录 思维导图 基本概念 进程 进程的创建 进程间的通信 进程池 线程 线程的创建 子线程的执行顺序 同步&互斥 互斥…

惊讶,日本用“Excel”作画,中国却用“Excel”造“另类”软件

精益求精 表格是一项伟大的创造&#xff0c;它的出现改变了人类记录、分析和展示数据的方式。 随着科技的日益月异的更新&#xff0c;从最早的纸质表格到现代化的电子表格&#xff0c;人类对表格的改造也在不断的升级和进步。 最初的纸质表格的简单记录&#xff0c;无法进行复…

企业权限管理(八)-登陆使用数据库认证

Spring Security 使用数据库认证 在 Spring Security 中如果想要使用数据进行认证操作&#xff0c;有很多种操作方式&#xff0c;这里我们介绍使用 UserDetails 、 UserDetailsService来完成操作。 UserDetails public interface UserDetails extends Serializable { Collecti…

汇聚行业精英,共探创新之道:首届NDI生态系统行业峰会即将登陆北京!

IP化和轻量化是媒体制播技术发展的主要趋势。为了推进媒体行业的IP制播技术应用发展&#xff0c;提供一个专业、全面的媒体技术交流平台&#xff0c;长沙千视电子科技有限公司将联合NDI官方、NDI生态产品厂家和NDI技术应用媒体单位于2023年8月22日在北京举办国内首届NDI生态系统…

嵌入式开发学习(STC51-11-中断系统)

内容 外部中断-使用独立按键K3控制LED亮灭&#xff1b; 定时器&#xff08;中断&#xff09;-通过定时器0中断控制D1指示灯间隔1秒闪烁&#xff1b; 串口通信&#xff08;中断&#xff09;-通过串口&#xff08;UART&#xff09;实现与PC机对话&#xff0c;51单片机的串口收…

Leetcode算法递归类—合并两个有序链表

目录 21. 合并两个有序链表 题解&#xff1a; 代码&#xff1a; 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例 1&#xff1a; 输入&#xff1a;l1 [1,2,4], l2 [1,3,4] 输出&#xff1a;[1,1,2,3,4,4]示例 2&a…

logstash 采集 docker 日志

1、nginx容器部署 参考&#xff1a;nginx容器部署 将容器内的nginx日志文件映射到宿主机/home/logs/nginx目录下 注意&#xff1a;并且需要需要将日志的输出格式修改为json 2、编辑vim /opt/logstash-7.4.2/config/nginx-log-es.conf 文件&#xff0c;收集docker nginx容器日…

【时间格式引发的事故】

时间格式引发的事故 背景实战演示结论 背景 前不久写了一个删除数据接口&#xff0c;条件是根据时间删除时间后面的数据。入参是 时间字符串。后台的时间格式 是 yyyyMMdd。然后当时前端传参数的时候&#xff0c;随意的传了2023-07-31的时间&#xff0c;然后将该表的数据全部删…

CCLINK IE转MODBUS-TCP网关modbus tcp协议详解

你是否曾经遇到过需要同时处理CCLINK IE FIELD BASIC和MODBUS两种数据协议的情况&#xff1f;捷米的JM-CCLKIE-TCP网关可以帮助你解决这个问题。 捷米JM-CCLKIE-TCP网关可以分别从CCLINK IE FIELD BASIC一侧和MODBUS一侧读写数据&#xff0c;然后将数据存入各自的缓冲区。接着…

【学习】若依源码(前后端分离版)之 “ 用户管理根据不同角色、部门显示数据范围”

大型纪录片&#xff1a;学习若依源码&#xff08;前后端分离版&#xff09;之 “ 用户管理根据不同角色、部门显示数据范围” 前端部分后端部分“ /list " 方法" /treeselect " 方法 结语 起因是我想做一个根据不同角色以及其所在的部门展示其相应的信息&#x…

StarRocks 3.1重磅发布,云原生湖仓新范式再升级!

StarRocks 自4月底发布3.0版本&#xff0c;拥抱云原生&#xff0c;开启极速统一的湖仓新范式&#xff1b;8月7日&#xff0c;StarRocks 正式发布全新3.1版本&#xff0c;全面提升云原生存算分离构架、极速数据湖分析、物化视图等重量级特性&#xff0c;让用户更简单的实现极速统…

前端性能优化之性能优化的指标和工具(chrome devtools、lighthouse、webpagetest)

文章目录 引言一、为什么要进行web性能优化二、RAIL测量模型1. 什么是RAIL2. 性能测量工具 三、性能测量工具的使用和性能指标以及优化目标1. Chrome DevTools1. 打开调试工具方式和配置2. network下的几个性能指标1. requests 请求总数2. transferred实际从服务器下载的数据量…

uni-app:实现点击按钮,进行数据累加展示(解决数据过多,导致出错)

效果 代码 核心代码 一、标签显示 <!-- 加载更多 --> <view class"load_more" v-if"info.length > pageNum * pageSize" tap"loadMore">加载更多 </view> v-if"info.length > pageNum * pageSize"&#xf…

主数据管理案例-某研究所

1、 背景介绍及难点分析 某军工研究所是机电类科研生产一体化研究所&#xff0c;具有多品种、小批量、离散性、央企、军工保密等特点&#xff0c;在数据管理系统和研制管理体系的控制下&#xff0c;设计、工艺、 制造、试验、售后服务等环节都产生了大量的数据。在管理信息化、…

影像维修工程师专项技能培训

最近遇到很多咨询的人员都在对医疗行业产生疑惑&#xff0c;新闻报道说很多医院、公司的领导都被查&#xff0c;这样会不会影响设备维修方面&#xff0c;对后期找工作等有没有影响&#xff1f;总不能学好了技术却没有发挥的余地&#xff1f; 最近确实是国家整体在对医疗方面做…

Win11 VS2022 配置CGAL-5.6

由于项目要用到几何库CGAL&#xff0c;因此做了配置。采用的是官方文档中的“Installing from the Source Archive”方式。 1. 下载安装CGAL &#xff08;1&#xff09;CGAL-5.6.zip下载地址&#xff1a;Releases CGAL/cgal GitHub 下载下图所示的两个文件。 &#xff08…

LeetCode面向运气之Javascript—第27题-移除元素-98.93%

LeetCode第27题-移除元素 题目要求 一个数组nums和一个值val&#xff0c;你需要原地移除所有数值等于val的元素&#xff0c;并返回移除后数组的新长度 举例 输入&#xff1a;nums [3,2,2,3], val 3 输出&#xff1a;2, nums [2,2] 输入&#xff1a;nums [0,1,2,2,3,0,4,2…

【C++】——模板

目录 泛型编程函数模板函数模板的概念函数模板格式&#xff1a;函数模板的原理函数模板的实例化模板参数的匹配原则 类模板类模板定义格式类模板的实例化 泛型编程 泛型编程&#xff1a;编写与类型无关的通用代码&#xff0c;是代码复用的一种手段。模板是泛型编程的基础 引例…

并发——线程池实践

文章目录 1. 使用 ThreadPoolExecutor 的构造函数声明线程池2.监测线程池运行状态3.建议不同类别的业务用不同的线程池4.别忘记给线程池命名5.正确配置线程池参数常规操作美团的骚操作 简单总结一下我了解的使用线程池的时候应该注意的东西&#xff0c;网上似乎还没有专门写这…

带你了解科研院所

一、什么是科研院所 研究院是独立于教育部和高校系统之外的&#xff0c;以科研工作为业务核心的各级、各类研究机构。独立研究院有很多种&#xff0c;其中实力最强、名气最大、分布最广、数量最集中的是直属国务院的中科院、社科院两大科研系统中的各类研究所和研究中心。 两大…