Lua语法(一)

简介: Lua语法(一)

简介

  Lua是一种轻量级的脚本语言,旨在嵌入应用程序中作为扩展语言使用。它由巴西里约热内卢天主教大学(Pontifical Catholic University of Rio de Janeiro)的一组研究人员于1993年开发而成。

  Lua的设计目标是提供一种简洁、高效、可嵌入和可扩展的脚本语言。它采用了简单的语法和动态类型系统,具有自动内存管理机制,以及一组基本的数据类型(包括nil、布尔、数字、字符串、表等)。Lua还支持面向对象编程、函数式编程和协同程序(coroutines),为开发者提供了很大的灵活性。

  Lua可以被嵌入到其他主机语言(如C、C++、Java等)中,并通过提供简单的API接口进行交互。这使得开发者可以在自己的应用中使用Lua作为扩展语言,实现更高级的脚本功能,而不是使用繁琐的主机语言编写大量的代码。

  Lua在游戏开发、嵌入式系统、网络编程、脚本扩展等方面得到了广泛应用。它的性能出色,具有较小的内存占用和快速的执行速度,因此在需要高效率和资源受限的环境中很受欢迎。

  总的来说,Lua是一种简洁、轻量级、高效的脚本语言,非常适合用于嵌入式环境中,为应用程序提供灵活、可扩展的脚本功能。

正文

语言基础

一、语法规范

1.Lua区分大小写,例如: and 和And不一样

2.Lua标识符和名称有字母、数字和下划线组成(不能用数字开头),下划线+大写字母通常被Lua用作特殊用途,避免将其用作其他用途

3.注释

​ 单行注释:

-- print("hello,lua")

​ 多行注释:

--[[
print("hello.lua")
--]]

小技巧——快速取消多行注释:

在多行注释的开头添加一个 - 可以让多行注释失效,从而取消多行注释

---[[
print("hello.lua")
--]]

二、类型和值

lua语言有8种基本类型

nil         空
boolean        布尔
number        数值
string        字符串
userdata    用户数据
function    函数
thread        线程    
table        表
print(type(nil))
print(type(true))
print(type(1.1*3))
print(type("hello lua"))
print(type(io.stdin))
print(type(print))
print(type(type))
print(type({
   
   }))
print(type(type(X)))
--输出如下
nil      
boolean
number
string
userdata
function
function
table
string

注:如果一个变量赋值给他nil,那么表示被销毁

三、数值运算

加减乘除,取余,大于小于,略。

lua5.3新增方法:

相当于普通除法后向下取整

3//2        --输出1
3//2.0        --输出1.0

数学库

例如三角函数,取整,绝对值,平方等,略。

-- 例如:
math.sin(20)
--其中math.modf是取整函数,是向0取整,意思是不管这个数是正还是负,向0的方向取整
math.modf(-1.5)     --输出-1
math.modf(1.5)        --输出1

数学库函数

随机数

随机数也是数学库的函数,但是需要单独写,有注意事项

基本用法:

使用随机数前需要添加上随机数种子,否则输出的随机数是固定的。

-- 这里我写了两遍输出随机数,这可不是随便写的,是故意的,因为第一次的随机数是固定的,第二次才是随机的。有没有被坑到?
math.randomseed(os.time())
print(math.random(5))
print(math.random(5))    --意思是在1-5  这5个数之间随机取一个
--如果是 math.random(7,9)那么就是在7-9 这3个数之间随机取一个

lua数值表示范围

这个也是属于数学库函数

math.maxinteger

四、字符串

字符串函数

字符串库

string.sub 截取一段
--例如
string.sub("hello",1,1)        --输出  h
--解释  string.sub(s,i,j) ,从字符串s中提取第i个到第j个字符,包含ij
--其中 ij可以为负数,表示倒数,例如-1表示倒数第一个字符,-2表示倒数第二个字符
string.sub("hello",2,-2)    --输出    ell
string.format 格式化字符串
----常用格式化----
%d  表示整数
%02d 表示 输出两位数,前面用0填充
%x    表示输出为16进制格式的整数
%f    表示输出为浮点数
%.4f    表示输出为小数部分有四位
%s    表示输出为字符串
d=5;m=8;y=1998
string.format("%02d/%02d/%04d",d,m,y)    --输出05/08/1998
string.format("pi=%.4f",math.pi)        --输出pi=3.1416
str="hello"
print(string.format("world %s",str))    --输出 world hello
print(string.format("x=%d y=%d",10,20))    --输出 x=10 y=20
string.find 查找某个字符串在第几个位置,从1开始
string.find("hello world","wor")    --输出  7  9  表示第7到第9个字符串
string.find("hello world","war")    --输出 nil
string.gsub (Global SUBstitution)找到某个字符并替换为指定字符
-- 查找 l 字符, 用 .  替代,输出替换后的字符串,并且输出替换的个数
string.gsub("hello world","l",".")    --输出 he..o wor.d    3
-- 查找 ll 字符,用 . 替代
string.gsub("hello world","ll","..")    --输出 he..o world    1
string.gsub("hello world","ll",".")        --输出 he.o world    1
string.rep 重复某个字符串
string.rep("a",2^20)    --返回一个 1MB 大小的全是a的字符串
string.rep("a",3)        --返回字符串 "aaa"
string.len 返回该字符串的长度
str=string.rep("a",3)
print(string.len(str))        --输出 3 ,这个方法与 #"aaa" 方法等价
string.reverse 字符串翻转
string.reverse("abc")        --输出 "cba"
string.lower 将字符串转换成字母小写
string.upper 将字符串转换成字母大写
string.byte 与 string.char 互转字节和字符
print(string.char(97))        --输出 a
print(string.byte("a"))        --输出 97
-----拓展------
i=97
print(string.char(i,i+1,i+2))    --输出 abc

print(string.byte("abc",2))        --输出 98
print(string.byte("abc",-1))    --输出 99
print(string.byte("abc",1,2))    --输出 97    98  这里表示的是字符串第一个到第二个字符的字节是什么
print(string.byte("abc",1,-1))    --输出整个字符串对应的字节

utf8库

lua5.3支持

1.字符串常量

单引号和双引号等价

a="hello"
a='hello'

输出字符串长度

print(#"hello")            --输出 5 
--------------------------------
a="hello"
print(#a)                --输出 5

lua支持的转义字符

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

2.多行字符串

str = [[
123
hello
nihao
]]
print(str)

--输出
123
hello
nihao

3.字符串与数字的强制类型转换

  • 数字转字符串
print(tostring(10)=="10")        --输出true

​ 使用 .. 连接符号,注意这里的符号前后都有一个空格

print(10 .. 20)        --输出 1020
  • 字符串转数字

​ 字符串转数字,不同进制的数字

print(tonumber("   -5 "))            --输出  -5
print(tonumber(" 10e4 "))            --输出  100000

--指定进制的转换
print(tonumber("100110",2))            --输出  38
print(tonumber("987",8))            --输出  nil,因为9超过了8进制,所以返回空 nil
print(tonumber("fff",16))            --输出  4095
print(tonumber("-ZZ",36))            --输出  4294966001

​ 直接使用加号,可以将字符串相加后变为数值

print("10"+1)        --输出 11

五、表

类似于数组,map,类的数据结构

-------初体验
a={
   
   }
m="n"
a[m]=10            --这里 "n"是键,10是值
print(a["n"])    --输出 10
a[3]="hello"    --这里 3 是键,"hello"是值
a["n"]            --这里 "n"是键,10是值
m=3
print(a[m])            --这里 3是键,"hello"是值
a["n"] = a["n"]+1    --这里a["n"]=11
a[3]=20
print(a[3])            --输出20

表标准库

table.insert 插入
t={
   
   }
table.insert(t,"one")
table.insert(t,"two")
table.insert(t,3,10)
for k, value in ipairs(t) do
    print(k,value)
end
--输出
1    one
2    two
3    10
table.remove 删除某元素
t={
   
   }
table.insert(t,"one")
table.insert(t,"two")
table.insert(t,3,10)
table.remove(t,2)
for k, value in ipairs(t) do
    print(k,value)
end
--输出
1    one
2    10
table.move 移动元素
---table.move(a,e,f,t)
---表示将表a 的 e到f 上的元素移动到 t的位置上
t={
   
   }
table.insert(t,"one")
table.insert(t,"two")
table.move(t,1,#t,2)
t[1]="move"
for k, value in ipairs(t) do
    print(k,value)
end

--输出
1    move
2    one
3    two

1. 表构造器

可以分为记录式和列表式

table = {
   
   
    color="red",        --记录式
    point=5,
    {
   
   x=0,y=0},            --列表式
    {
   
   x=1,y=1},
    {
   
   x=2,y=2}
}

print(table[1].x)            --输出0
print(table.point)            --输出5

2.遍历表

通常,遍历表都是随机的,但是元素只会遍历输出一次,

----------------使用pairs是随机输出-------------------
table = {
   
   
    color="red",        --记录式
    point=5,
    {
   
   x=0,y=0},            --列表式
    {
   
   x=1,y=1},
    {
   
   x=2,y=2}
}
for k, v in pairs(table) do
    print(k,v)
end
--输出
1    table: 000000000102a860
2    table: 000000000102a7e0
3    table: 000000000102aca0
point    5
color    red
------------使用 ipairs 是顺序输出------------------

table={
   
   10,print,12,"hi"}
for k, v in ipairs(table) do
    print(k,v)
end
--输出
1    10
2    function: 00000000684989c0
3    12
4    hi

还有用关键字遍历的方式

table={
   
   10,print,12,"hi"}
for i = 1, #table do
    print(i,table[i])
end
--输出
1    10
2    function: 00000000684989c0
3    12
4    hi

六、函数

格式

function add(a)
    local sum =0
    for i = 1, #a do
        sum = sum +a[i]
    end
    return sum
end
t = {
   
   1,2,3,4,5}
print(add(t))

1.多返回值

function add(a)
    return a[1],a[2]
end
t = {
   
   1,2,3,4,5}
print(add(t))
--输出
1    2

2. 可变长参数函数

function add(...)
    local s=0
    for _, value in ipairs(...) do
        s=s+value
    end
    return s
end
t = {
   
   1,2,3,4,5}
print(add(t))
--输出
15

3.函数 table.pack

将一些零散的值返回成一个表

print(type(table.pack(1,2,3,4)))
--输出
table

4.函数 table.unpack

将一个表拆散成多个变量

print(table.unpack({
   
   1,2,3,4,5}))
--输出    1    2    3    4    5

a,b=table.unpack({
   
   1,2,3,4,5})
print(a,b)
--输出    1    2

print(table.unpack({
   
   1,2,3,4,5},2,3))
--输出    2    3

f = string.find
print(f(table.unpack({
   
   "hello","ll"})))
--输出    3    4

5.尾递归调用

function f(x)
    x=x+1
    return g(x)
end

七、控制结构

if ...else then ...end

sum = 0
a=10
if a<0 then
    sum=1
elseif a<2 then
    sum=2
elseif a<4 then
    sum=4
else
    sum=5
end
print(sum)
--输出 5

while do

a=1
sum=0
while a<10 do
    sum = sum+1
    a=a+1
end
print(sum)
--输出    9

repeat...until

sum =10
repeat
    sum = sum-1
    print(sum)
until sum<0

for 循环

sum =10
t = {
   
   1,2,3,4}
for k, value in ipairs(t) do
    print(k,value)
end
--输出
1    1
2    2
3    3
4    4



for i = 1, 10, 2 do
    print(i)
end
--输出
1
3
5
7
9

八、输入输出

io.write

io.write和print 的区别有

  • print会自动换行

  • io.write可以重定向,print不能

  • io.write可以精准控制输出流,例如输出个数
io.write("test")
io.write("test")
print("hello")
print("hello")
--输出
testtesthello
hello
file = io.open("data.txt","a")
io.output(file)
io.write("www.com")
io.close(file)

io.read

等同于 io.input():read(args)

从当前输入流中读取字符串

这个需要参数

"a"  读取整个文件
"l"     读取下一行(丢弃换行符)
"L"  读取下一行(保留换行符)
"n"  读取一个数值
num  以字符串读取num个字符

io.lines

io.input("data.txt")
for line in io.lines() do
    print(line)
end
--输出
hel
ddd

---上面的可以写成
for line in io.lines("data.txt") do
    print(line)
end
-------------------

--如果给io.lines 一个参数,那么这个数字表示一行的大小,可以减少访问次数
--加入data.txt有两行数据
-------------下面执行一次---------------
num=0
for line in io.lines("data.txt",2^8) do
    print(line)
    num = num+1
end
print(num)
--num输出 1
------------下面执行两次-------------
num=0
for line in io.lines("data.txt") do
    print(line)
    num = num+1
end
print(num)
--num输出  2

简单IO模型

简单IO模型包含io.input,io.output, io.read, io.write

io.input输入流

--1.输入流
--注意这个文件默认处于当前工作空间下才能读取到
--当前工作空间参考vscode工作区概念
--另外,需要print或者io.write输出读取到的内容

--1.1默认输入流
--默认的io.input输入流是控制台,所以执行后可以在控制台输入字符,然后回车后会读取
io.input()
print(io.read())
--输入 aaa
--输出 aaa

--2指定输入流为某文件
io.input("data.txt")
print(io.read())        --读取一行

--2.1维持默认输入流
--如果此时在后面的io.input不添加参数,那么默认输入流默认是“data.txt”文件
--例如:
io.input("data.txt")
print(io.read())        --读取一行
io.input()
print(io.read())        --读取一行

--2.2修改输入流
--如果添加参数,那么会改变默认输入流
io.input("data.txt")
print(io.read())        --读取一行
io.input("ni.txt")
print(io.read())        --读取一行

io.output输出流

--1.输出流
--默认输出流是控制台输出,默认输出到控制台
io.output()
io.write("niho")
--输出 niho

--2.指定文件输出流
io.output("hello.txt")
io.write("niho")
--这段文字输出到这个文件,文件不存在会自动创建

综合案例:利用简单IO模型,读取整个文件的内容并输出

--方式一
io.input("data.txt")
for i = 1, math.huge do
    local line = io.read("L")
    if line==nil then
        break
    end
    io.write(line)
end

--方式二 利用IO.lines
io.input("data.txt")
for line in io.lines() do
    io.write(line,"\n")
end

--方式三 将所有行读取到表里面
io.input("data.txt")
t={
   
   }
for line in io.lines() do
    t[#t+1] = line            --读到表里
end
for k, value in pairs(t) do
    print(k,value)            --输出表
end

完整IO模型

与简单IO模型相比,完整IO模型更适用于多个文件

完整IO模型是基于file句柄然后加上 : 引号来调用特别的方法,让IO更加强大

--读取文件
file = io.open("data.txt","r")
print(file:read("a"))
file:close()

完整IO模型中的方法大多参考的C语言中的IO方法

file = io.open("data.txt","r")
file:seek("set",1)        --设置文件句柄从哪个字符开始读,第一个字符是0,第二个是1,这里从第二个字符开始
print(file:read("a"))
--输出
输出结果将从第二个字符开始

还有其他很多方法,可以参考c语言对应方法的用法

文件I/O

io.open/io.close

读取文件,第一个参数是文件名,第二个是打开的权限

file = io.open("test.txt","r")
io.input(file)
print(io.read())//读取一行
io.close(file)

九、常见系统命令

os.rename

给文件改名

--第一个参数是旧名字,第二个参数是新名字
os.rename("data.txt","da.txt")

os.remove

删除文件

os.remove("ww.lua")

os.getenv

获取环境变量

--参数是环境变量的变量名
print(os.getenv("MAVEN_HOME"))
--输出
输出Maven的环境变量

os.execute("java -version")

在当前系统执行一条信息

io.popen

和上面的作用一样,在当前系统执行一条命令,但是可以设置为 r模式,将流信息重定向输入到文件中

file = io.popen("java -version","r")
目录
相关文章
|
4月前
Lua语法(六)——面相对象编程
Lua语法(六)——面相对象编程
35 0
|
4月前
|
Java
Lua语法(五)——垃圾回收
Lua语法(五)——垃圾回收
114 0
|
4月前
Lua语法(四)——协程
Lua语法(四)——协程
58 0
|
4月前
|
索引
Lua语法(三)——元表与元方法
Lua语法(三)——元表与元方法
50 0
|
4月前
|
缓存
Lua语法(二)——闭包/日期和时间
Lua语法(二)——闭包/日期和时间
95 0
|
6月前
|
存储 缓存 NoSQL
Redis系列学习文章分享---第十三篇(Redis多级缓存--JVM进程缓存+Lua语法)
Redis系列学习文章分享---第十三篇(Redis多级缓存--JVM进程缓存+Lua语法)
84 1
|
7月前
|
NoSQL JavaScript Java
Lua开发环境搭建和基础语法
Lua开发环境搭建和基础语法
154 1
|
7月前
|
Java Kotlin 索引
Lua 起航 —— 一些常用基础语法
Lua 起航 —— 一些常用基础语法
76 1
|
存储
Lua基本语法
Lua基本语法
|
存储 Java 应用服务中间件
Lua语法讲解
Lua语法讲解
94 0