lua教程

https://moonbingbing.gitbooks.io/openresty-best-practices/content/lua/class.html

lua最核心的就是table,table中的变量、函数就构成了一个对象,可以理解成,一个table就等同于面向对象编程。

同时一个table,就可以成为一个module被别的lua代码导入,使用:

require("module")就可以导入module.lua文件中定义的table作为一个模块。lua还会把这个模块的table声明为一个全局变量,这样在require之后,就可以直接使用table的名字来访问table里的函数或者变量了。

require的返回值

require “xxx” 某个模块后

1.如果该模块自身有返回值,且模块加载成功,那么require 的返回值就是该模块的返回值

2.如果模块没有返回值,如果require加载模块成功,就返回ture

3.require 内部将返回值储存在:package.loaded表中。

(即:package.loaded[xxx]中)

4.例子

(1)main.lua

x = require "test"

function Call()
    x.show()
end

(2)test.lua

local tb = {}
function tb.show()
    print("it is ok")
end

return tb

(3)testLua.cpp

int _tmain(int argc, _TCHAR* argv[])
{
    lua_State *L = luaL_newstate();
    luaL_openlibs(L);
    luaL_dofile(L,"Lua//main.lua");

    lua_getglobal(L,"Call");
    lua_pcall(L,0,0,0);

    return 0;
}

https://www.jianshu.com/p/d727825816ee

2、--是注释符

3、成员访问符

有句号和冒号两种

通过句号调用函数时,不会将self作为参数传入给函数,所以如果函数需要用self,则会报错。

而冒号调用函数时,会将self作为参数传入。

4、双点是字符串拼接

local a = "hello".."world"

上面的a就是helloworld,等价于别的语言的字符串+运算。

5、and or

逻辑运算时就是普通的与/或逻辑,在lua中,数值为0为true而不是false,这一点与其他语言不同

但是lua的and和or会返回操作数

  • and 返回第一个不为真的操作数,如果都为真,则返回最后一个操作数
a = 0 and 1
a为1
a = nil and 1
a为nil

  • or 返回第一个为真的操作数,如果都不为真,则返回最后一个操作数
a = 0 or 1
a 为0
a = nil or false
a 为false

6、ipairs pairs

两个都是用来迭代遍历集合和table的,但有不同

ipairs是将被迭代的对象当成数组一样,会从下标1开始遍历,一旦发现下一个下标的元素不存在,就会结束迭代。

local tabFiles = {
        [1] = "test2",
        [6] = "test3",
        [4] = "test1"
    }

for k, v in ipairs(tabFiles) do    --输出"test2",在key等于2处断开
    print(k, v)
end
local tabFiles = {
    [2] = "test2",
    [6] = "test3",
    [4] = "test1"
}

for k, v in ipairs(tabFiles) do  --[[什么都没输出,为什么?因为控制变量初始值是按升序来遍历的,当key为1时,value为nil,此时便停止了遍历, 所有什么结果都没输出]]--
    print(k, v)
end

而pairs就是普遍意义上的遍历所有的元素

local tabFiles = {
    [2] = "test2",
    [6] = "test3",
    [4] = "test1"
}

for k, v in pairs(tabFiles) do  --输出2 test2, 6 test3, 4 test1
    print(k, v)
end
local tabFiles = {"alpha", "beta", [3] = "no", ["two"] = "yes"}  for i,v in ipairs(tabFiles ) do    --输出前三个   备注:因为第四个key不是整数
    print( tabFiles [i] )   
end   
  
for i,v in pairs(tabFiles ) do    --全部输出   
    print( tabFiles [i] )   
end 

https://www.runoob.com/note/11315

7、变量类型

Lua 变量有三种类型:全局变量、局部变量、表中的域。

Lua 中的变量全是全局变量,哪怕是语句块或是函数里,除非用 local 显式声明为局部变量。

局部变量的作用域为从声明位置开始到所在语句块结束。

变量的默认值均为 nil。

8、下标从1开始

9、table

10、local xxx do xxx end

上面的例子没有截取完整,下面的代码就是函数的定义和do语句块的结束。

我们可以看到有两处声明了同名的对象fill_node_info,在lua中没有使用local前缀的都是全局对象,但是这个代码中里面的fill_node_info并不是一个全局对象,这其实是lua 的语法特性:

function fill_node_info() 是等价于 fill_node_info=function()的,所以里面的fill_node_info只是对外面的local fill_node_info的重新赋值,这时候fill_node_info就变成了一个函数,也是局部对象;而这里的do的作用就是保护语句块中的一些数据而已。

do end等价于c++的{}作用域。

11、io.write

io.write在没有指定文件时,等同于print

12、执行lua脚本

和python类似,命令行执行lua进入console

lua code_file.lua 运行代码

13、判断lua的table是否为空

local mytable = {}
 
local mytable2 = {333,"hello",666}
 
if next(mytable) == nil then
    print("mytable is true")
else
    print("mytable is false")
end
 
if next(mytable2) == nil then 
    print("mytable2 is true")
else
    print("mytable2 is false")
end

或者

local mytable = {}
if #mytable == 0 then
    print("empty table")
end

14、字符串日前转时间戳

https://blog.csdn.net/chunniaozheng2370/article/details/101061249

snippet

local function get_timestamp(time_str)
    -- format "2022-02-25T21:54:07.7164964+08:00"
    local _, _, year, month, day, hour, min, sec = string.find(time_str, "(%d+)-(%d+)-(%d+)T(%d+):(%d+):(%d+)")
    return os.time({year=year, month = month, day = day, hour = hour, min = min, sec = sec})
end

15、table.concat

https://blog.csdn.net/LIQIANGEASTSUN/article/details/46592005

http://lua-users.org/wiki/TableLibraryTutorial

tab = {"a", "c", "d", "b"}
--(4)
    -- 四个参数,参数一:表(tab),参数二:分隔符 (" - "),
    -- 参数三:起始位置(2),参数四:结束连接位置,作用为连
    -- 接tab中所有的value,value 间以 " - " 隔开, 从 tab 
    -- 的第二个value  开始连接,到 tab 的 第 3 个 value结束连接

    print( table.concat(tab, " - ", 2, 3))  
    --> 输出结果: c - d

简单来说就是将table的字符串拼接起来,指定连接符,以及从第几个到第几个元素的拼接;只有table参数是必传的,其他的都是可选的,默认是连接符为空,从头到尾拼接

将table中的元素拼接成字符串,每个元素都必须支持转换成字符串

Concatenate the elements of a table to form a string. Each element must be able to be coerced into a string.

concat will fail on a table that contains tables because they cannot be coerced into strings

table中的数组或者kv对不能被concat,目前来看只有数字和字符串是可以concat的,而且只能是可以下标索引的元素才可以,例如 a = {1,2,3,"hello"} a[4]->"hello",如果出现不能下标访问的,例如a = {1,2,3,x=1,y=2},那么concat只会输出123,后面的x、y都不会拼接输出

并且,下标是跳过非下标访问元素的数值,例如下面的table,下标从1开始,最大的是5,对应的888

16、select函数

https://www.cnblogs.com/wangyueyouyi/p/9915644.html

lua使用...来表示变长参数,{...}表示变长参数的数组,#{...}表示变长参数的长度,

而select函数可以用来返回变长参数的长度,以及指定从第几个参数开始遍历

function fun(...)                 --此处的...表示可变参数
    for i in pairs({...})  do     --此处的{...}表示可变参数构成的数组
        xxx
    end
end

select(n, ...)  --数字n表示起点,select(n, ...)返回从起点n到结束的可变参数,比如:

n=3,... 是 0,1,2,3,4,5

则 select(n, ...) 就表示...中从第3个到最后一个的多个数:2,3,4,5。并且2,3,4,5是4个数,不是列表或其他的数据结构

select('#', ...)  --返回可变参数的数量

方法1:

function f(...)
    print (#{...}))
end
f(1,2,3)>>3

方法2:

function f(...)
    local x = {...}
    print (#x))
end
f(1,2,3)>>3

17、lua的函数return

这里是特意备注下,lua中函数如果没有在任何语句块直接return的话,必须结束函数

function correct_example()
    return 
end

function wrong_example()
    return
    print(123)
end

如果想直接return,则需使用某个语句块,例如if或者do等

function correct_example()
    do
        return
    end                                 
end

18、lua的table都是引用

t1 = {a=123}
t2 = {table1 = t1}
t3 = {table2 = t1}
print(t1.a) -- => 123
print(t2.table1.a) -- => 123
print(t3.table2.a)  -- => 123
t1.a=456
print(t1.a) -- => 456
print(t2.table1.a) -- => 456
print(t3.table2.a)  -- => 456

所以用lua写代码的时候,特别要注意这点,避免出现预料之外的数据

在lua中,如果数据类型是引用传参的,例如table、string,即使使用了local的限制,都是引用处理,一处修改,别处也会可见。

19、lua避免循环require的处理

lua的require会先判断某个模块是否已经加载了,是的话就直接返回,否则才加载模块数据,因此来避免循环引用的问题。

20、lua数组append元素

使用table.insert

foo = {}

table.insert(foo,"bar")

table.insert(foo,"baz")

21、lua string.find

https://riptutorial.com/lua/example/20535/string-find--introduction-