Lua语法

Lua快速入门:https://blog.csdn.net/mrdo_home/article/details/92833999

概要:1.table特性;2.table的构造;3.table常用函数;4.table遍历;5.table面向对象:https://www.cnblogs.com/lexiaoyao-jun/p/5208230.html

Lua表(table)的用法_个人总结:https://www.cnblogs.com/mengmengxia/p/9234183.html

 

 

数据类型:
nil   //只有nil属于该类,表示一个无效值
boolean //包含两个值,false和true
number  //表示双精度类型的实浮点数
string  //字符串由一对双引号或单引号表示
function //由C或lua编写的函数
userdata //表示任意存储在变量中的C数据结构
thread   //表示执行的独立线路
table    //其实是一个关联数组,数组的索引可以是数字、字符串或表类型。


boolean 类型只有两个可选值:true(真) 和 false(假),Lua 把 false 和 nil 看作是 false,其他的都为 true,数字 0 也是 true:
在 Lua 里表的默认初始索引一般以 1 开始。
table 不会固定长度大小,有新数据添加时 table 长度会自动增长,没初始的 table 都是 nil。

=================================================
注释:
-- 单行注释
--[[
    多行注释
    多行注释
--]]
=================================================
标示符:
最好不要使用下划线加大写字母的标示符,因为Lua的保留字也是这样的。
Lua 不允许使用特殊字符如 @, $, 和 % 来定义标示符。
Lua 是一个区分大小写的编程语言。
=================================================
变量:
在默认情况下,变量总是认为是全局的;
全局变量不需要声明,给一个变量赋值后即创建了这个全局变量,
访问一个没有初始化的全局变量也不会出错,只不过得到的结果是:nil。

如果你想删除一个全局变量,只需要将变量赋值为nil。

变量在使用前,必须在代码中进行声明,即创建该变量。(主要是local变量,全局变量不需要声明就能立即使用)
编译程序执行代码之前编译器需要知道如何给语句变量开辟存储区,用于存储变量的值。
局部变量的作用域为从声明位置开始到所在语句块结束。
Lua 中的变量全是全局变量,那怕是语句块或是函数里,除非用 local 显式声明为局部变量。
Lua 变量有三种类型:全局变量、局部变量、表中的域。

尽可能使用局部变量,这样做的好处:
避免命名冲突;
访问局部变量的速度比全局变量快;    
=================================================
赋值语句:
1、可以对多个变量同时赋值
    a,b = 10,2*x   -> a=10,b=2*x

2、当变量个数和值的个数不一致时:
    变量个数 > 值的个数             按变量个数补足nil
    变量个数 < 值的个数             多余的值会被忽略

3、多值赋值
    a, b = f()
    f()返回两个值,第一个赋给a,第二个赋给b。
=================================================
索引:
对table的索引使用方括号,
也提供.操作;

表:
a={} b={...}
表达式a.b等价于a[“b”],但不等价于a[b]

任何类型的变量,除了nil,都可以做为表项的键。
从简单的数值、字符串 到复杂的函数、表等等都可以;
同样,任何类型的变量,除了nil,都可以 作为表项的值。

给一个表项的值赋nil意味着从表中删除这一项,比如令a.b = nil,则把表a中键为“b”的项删除。
如果访问一个不存在的表项,其值 也是nil,比如有c = a.b,
但表a中没有键为“b”的项,则c等于nil
=================================================
循环:
1、while循环:
while(condition)
do
   statements
end

2、for循环:
2.1、数值for循环
for var=exp1,exp2,exp3 do  
    <执行体>  
end  
var 从 exp1 变化到 exp2,每次变化以 exp3 为步长递增 var,并执行一次 "执行体"。
exp3 是可选的,如果不指定,默认为1。

2.2、泛型for循环
泛型 for 循环通过一个迭代器函数来遍历所有值
a = {"one", "two", "three"}
for i, v in ipairs(a) do
    print(i, v)
end
i是数组索引值,v是对应索引的数组元素值。ipairs是Lua提供的一个迭代器函数,用来迭代数组。

3、repeat...until 循环
repeat
   statements
until( condition )
=================================================
流程控制:
if(布尔表达式)
then
   --[ 在布尔表达式为 true 时执行的语句 --]
end


if(布尔表达式)
then
   --[ 布尔表达式为 true 时执行该语句块 --]
else
   --[ 布尔表达式为 false 时执行该语句块 --]
end


if( 布尔表达式 1)
then
   --[ 布尔表达式 1 为 true 时执行该语句块 --]
   if(布尔表达式 2)
   then
      --[ 布尔表达式 2 为 true 时执行该语句块 --]
   end
end
=================================================
函数定义:
optional_function_scope function function_name( argument1, argument2, argument3..., argumentn)
    function_body
    return result_params_comma_separated
end

optional_function_scope:该参数是可选的制定函数是全局函数还是局部函数,未设置该参数默认为全局函数,
如果你需要设置函数为局部函数需要使用关键字 local。

function_name:指定函数名称

argument1,argument2,argument3...,argumentn:函数参数,多个参数以逗号隔开,函数也可以不带参数;

result_params_comma_separated: 函数返回值,Lua语言函数可以返回多个值,每个值以逗号隔开。


可变参数:
Lua 函数可以接受可变数目的参数,和 C 语言类似,在函数参数列表中使用三点 ... 表示函数有可变的参数。

function add(...)  
local s = 0  
  for i, v in ipairs{...} do   --> {...} 表示一个由所有变长参数构成的数组  
    s = s + v  
  end  
  return s  
end  
print(add(3,4,5,6,7))  --->25

=================================================
运算符:

算术运算符;
关系运算符;
    ~= 不等

逻辑运算符:
    and  与
    or   或
    not  非
    
其他运算符:
    ..  连接两个字符串
    #   一元运算符,返回字符串或表的长度
    
运算符优先级;

=================================================
字符串:

Lua 语言中字符串可以使用以下三种方式来表示:
    单引号间的一串字符。
    双引号间的一串字符。
    [[和]]间的一串字符。
    

字符串操作方法;

转义字符;    

格式化字符串;

字符串与整数相互转换;

连接字符串,计算字符串长度,字符串复制;

字符串匹配

=================================================
数组:
数组,就是相同数据类型的元素按一定顺序排列的集合,可以是一维数组和多维数组。

Lua 数组的索引键值可以使用整数表示,数组的大小不是固定的。


=================================================
迭代器:
泛型 for 在自己内部保存迭代函数,实际上它保存三个值:迭代函数、状态常量、控制变量。

array = {"Google", "Runoob"}
for key,value in ipairs(array)
do
   print(key, value)
end
// Lua 默认提供的迭代函数 ipairs


//每一次迭代,迭代函数都是用两个变量(状态常量和控制变量)的值作为参数被调用,
//一个无状态的迭代器只利用这两个值可以获取下一个元素。
function iter (a, i)
    i = i + 1
    local v = a[i]
    if v then
       return i, v
    end
end
 
function ipairs (a)
    return iter, a, 0
end
    
================================================
table表:
table 是 Lua 的一种数据结构用来帮助我们创建不同的数据类型,如:数组、字典等。


-- 初始化表
mytable = {}

-- 指定值
mytable[1]= "Lua"

-- 移除引用
mytable = nil
-- lua 垃圾回收会释放内存



Table 连接
fruits = {"banana","orange","apple"}
-- 返回 table 连接后的字符串
print("连接后的字符串 ",table.concat(fruits))

-- 指定连接字符
print("连接后的字符串 ",table.concat(fruits,", "))

-- 指定索引来连接 table
print("连接后的字符串 ",table.concat(fruits,", ", 2,3))

连接后的字符串     bananaorangeapple
连接后的字符串     banana, orange, apple
连接后的字符串     orange, apple



Table 排序
fruits = {"banana","orange","apple","grapes"}
print("排序前")
for k,v in ipairs(fruits) do
        print(k,v)
end

table.sort(fruits)
print("排序后")
for k,v in ipairs(fruits) do
        print(k,v)
end

排序前
1    banana
2    orange
3    apple
4    grapes
排序后
1    apple
2    banana
3    grapes
4    orange


Table 最大值
================================================
Lua模块与包:
Lua 加入了标准的模块管理机制,可以把一些公用的代码放在一个文件里,
以 API 接口的形式在其他地方调用,有利于代码的重用和降低代码耦合度。

Lua 的模块是由变量、函数等已知元素组成的 table,
因此创建一个模块很简单,就是创建一个 table,然后把需要导出的常量、函数放入其中,
最后返回这个 table 就行。


-- 文件名为 module.lua
-- 定义一个名为 module 的模块
module = {}
 
-- 定义一个常量
module.constant = "这是一个常量"
 
-- 定义一个函数
function module.func1()
    io.write("这是一个公有函数!\n")
end
 
local function func2()
    print("这是一个私有函数!")
end
 
function module.func3()
    func2()
end
 
return module


由上可知,模块的结构就是一个 table 的结构,
因此可以像操作调用 table 里的元素那样来操作调用模块里的常量或函数。
上面的 func2 声明为程序块的局部变量,即表示一个私有函数,
因此是不能从外部访问模块里的这个私有函数,必须通过模块里的公有函数来调用.



require函数:
require("<模块名>")  或者  require "<模块名>"

给加载的模块定义一个别名变量,方便调用:
-- test_module2.lua 文件
-- module 模块为上文提到到 module.lua
-- 别名变量 m
local m = require("module")
print(m.constant)
m.func3()


加载机制:
对于自定义的模块,模块文件不是放在哪个文件目录都行,
函数 require 有它自己的文件路径加载策略,它会尝试从 Lua 文件或 C 程序库中加载模块。

require 用于搜索 Lua 文件的路径是存放在全局变量 package.path 中;
当 Lua 启动后,会以环境变量 LUA_PATH 的值来初始这个环境变量。
如果没有找到该环境变量,则使用一个编译时定义的默认路径来初始化。

当然,如果没有 LUA_PATH 这个环境变量,也可以自定义设置,
在当前用户根目录下打开 .profile 文件(没有则创建,打开 .bashrc 文件也可以),
例如把 "~/lua/" 路径加入 LUA_PATH 环境变量里:
#LUA_PATH
export LUA_PATH="~/lua/?.lua;;"
文件路径以 ";" 号分隔,最后的 2 个 ";;" 表示新加的路径后面加上原来的默认路径。
接着,更新环境变量参数,使之立即生效。
source ~/.profile


C包:
Lua和C是很容易结合的,使用 C 为 Lua 写包。
C包在使用以前必须首先加载并链接,在大多数系统中最容易的实现方式是通过动态链接库机制。
Lua在一个叫loadlib的函数内提供了所有的动态连接的功能。
这个函数有两个参数:库的绝对路径和初始化函数。
local path = "/usr/local/lua/lib/libluasocket.so"
local f = loadlib(path, "luaopen_socket")
loadlib 函数加载指定的库并且连接到 Lua,然而它并不打开库(也就是说没有调用初始化函数),
反之他返回初始化函数作为 Lua 的一个函数,这样我们就可以直接在Lua中调用他。


一般情况下我们期望二进制的发布库包含一个与前面代码段相似的 stub 文件,
安装二进制库的时候可以随便放在某个目录,只需要修改 stub 文件对应二进制库的实际路径即可。

将 stub 文件所在的目录加入到 LUA_PATH,这样设定后就可以使用 require 函数加载 C 库了。

===========================================
元表:
在 Lua table 中我们可以访问对应的key来得到value值,但是却无法对两个 table 进行操作。
因此 Lua 提供了元表(Metatable),允许我们改变table的行为,每个行为关联了对应的元方法。

例如,使用元表我们可以定义Lua如何计算两个table的相加操作a+b。
setmetatable(table,metatable): 对指定 table 设置元表(metatable),
如果元表(metatable)中存在 __metatable 键值,setmetatable 会失败。
getmetatable(table): 返回对象的元表(metatable)。

mytable = {}                          -- 普通表
mymetatable = {}                      -- 元表
setmetatable(mytable,mymetatable)     -- 把 mymetatable 设为 mytable 的元表

mytable = setmetatable({},{})
getmetatable(mytable)                 -- 这回返回mymetatable

这块比较复杂;

================================================
array = {值1,值2,值3,} --这种比较好用
array = {[1] = 值1,[2] = 值2,} --容易出错 ,建议最好不要用

# 号,作用为获取字符串的长度 。
在lua中,注意是用在数组中 ,#号为获取数组中元素的个数

posted @ 2021-04-11 23:48  Grooovvve  阅读(171)  评论(0编辑  收藏  举报