LUA基础

循环

for

数值for循环, 语法:

for var=exp1,exp2,exp3 do 

    <执行体> 

end

exp3是可选的,如果不指定,默认为1

举例:

for i = 0, #ret, 1

do

         print("process: "..ret[i]["name"])

end

I 表示初始变量

#ret 表示表的长度

1表示每循环一次 I 的值增加多少,可以是负数

泛型for循环,语法:

for k, v in ipairs/pairs(a)

do

          <执行体> 

end

举例:

for k, v in pairs(ret)

do

         print(k, v)

end

ret是一个表

while

语法:

while(condition)

do

   statements

end

condition 可以括号也可以不用括号

举例:

i = 0

while true

do

         if i > #ret then

                   break

         end

         print(i)

         i = i + 1

end

i = 0

while i < #ret

do

         print(i)

         i = i + 1

        

end

repeat

语法:

repeat

   statements

until ( condition )

condition 可以括号也可以不用括号

举例:

i = 0

repeat

         print(ret[i]["name"])

         i = i + 1

until (i > #ret)

代码块

do end

关键字for 后面必须带do end

关键字while后面必须带 do end

then end

关键字if后面执行的代码需要用then  end包起来

function

end

关键字function定义的函数,结束要用end标识

条件语句

If语句

if(布尔表达式) –括号可以不要

then

   --[ 在布尔表达式为 true 时执行的语句 --]

end

if...else

if(布尔表达式)

then

   --[ 布尔表达式为 true 时执行该语句块 --]

else

   --[ 布尔表达式为 false 时执行该语句块 --]

end

函数

function

Lua函数可以返回多个值

Lua函数支持变参,然后通过for 来迭代访问参数

function print_arg(...)

         local args = {...}

         for _, v in ipairs(args)

         do

                   print(v)

         end

end

print_arg(1, 2, "hello", "world")

函数调用必须带括号, 除了单个参数的函数, 并且参数类型为字符串, 表构造器时, 可以不带括号

Lua可以返回函数

function print_arg(...)

         local args = {...}

         for _, v in ipairs(args)

         do

                   print(v)

         end

end

function return_function()

         return print_arg

end

_xxxprint_arg = return_function()

_xxxprint_arg("hello", "sysnap")

字符串

string

string库中所有的字符索引从前往后是1,2,...;从后往前是-1,-2,...

string库中所有的function都不会直接操作字符串,而是返回一个结果

string.byte(str, pos)可以把指定的位置的字符转为 ASCII 编码

string.char(asc1, ...) 可以把ASCII 编码转为字符,比如string.char(104, 104)

在lua5.1,同时也作为string类型的成员方法,既可以写成string.upper(s), 也可以s:upper()

查找

string.find(s, pattern,  [pos])

第1个参数:源字符串

第2个参数:待搜索之模式串

第3个参数:A hint, 从pos位置开始搜索,可以不写,默认是1

找到匹配返回:匹配串开始和结束的位置,否则返回nil,举例

pos = 1;

while true

do

         s1, s2 = teststr:find("123", pos)

         if(s1 == nil) then

                   break;

         end

         print("find str pos: ", s1, s2)

         pos = s1 + 1;

end

模式

字符大写表示补集,比如%W表示不是字母也不是数字

.

任意字符

%s

空白串

%p

标点,比如!,。?;

%c

控制字符,比如回车,换行符

%d

数字

%x

十六进制数字

%z

代表0的字符

%a

字母

%l

小写字母

%u

大写字母

%w

字母或者数字

字符集

[]

[%[%]]'匹配一对方括号。

[01] 匹配二进制数字。

[0-9a-fA-F] 匹配 16进制数,跟%x作用是一样的。

[0-7] 表示 [01234567]。

修饰符

+

匹配前一字符一次或多次

*

匹配前一字符0次或多次,最长匹配

-

匹配前一字符0次或多次,最短匹配.[ ] 里面-的意义见上面

?

匹配前一字符0次或1次

^

匹配字符串开头,如果放在[]里面,表示NOT意思

$

匹配字符串结尾

转义字符

%

'%' 用作特殊字符的转义字符

'%.' 匹配点;

'%%' 匹配字符 '%'。

转义字符 '%'不仅可以用来转义特殊字符,还可以用于所有的非字母的字符

捕获: 在模式中,用小括号括起来的子模式,它在匹配发生的时候截取小括号内模式匹配到的字符串,然后保存下来,默认最多保存 32 个,可以理解是sscanf,  括起来的模式串只是告诉LUA这个串匹配到的内容要存起来并返回

举例:

pair = "name = Anna"

_, _, key, value = string.find(pair, "(%a+)%s*=%s*(%a+)")

print(key, value)    --> name  Anna

 

date = "17/7/1990"

_, _, d, m, y = string.find(date, "(%d+)/(%d+)/(%d+)")

print(d, m, y)      --> 17 7 1990 

 

s = "then he said: "its all right"!"

a, b, quotedPart = string.find(s, "(["].-["])")

print(quotedPart)    --> "its all right"

 

一个空的捕获,也就是小括号里面什么内容也没有,它会返回当前字符串的比较操作进行到的位置

s = "then he said: "it's all right"!"

a, b, q = string.find(s, "()(["].-["])")

print(q)    --> 15

%后面接数字 1-9 表示用前面模式捕获的序号 1-9 对应的字符串来替换模式匹配的内容

local s = "am+dmf"

print(string.gsub(s, "()(m+)", "%1"))     -- a2+d5f     2

--匹配到m的时候,位置是2,所以第一个捕获()输出是2,这时%1表示第一个捕获的值,这里是2,这里把m改---为2,接着继续匹配,匹配到dmf这个m的时候,位置是5,这时%1的值是5

 

command{some text}将它们转换为XML风格的字符串:<command>some text</command>

s = string.gsub(s, "\(%a+){(.-)}", "<%1>%2</%1>")

 

举例

s = "Deadline is 30/05/1999, firm"

date = "%d%d/%d%d/%d%d%d%d"

print(string.sub(s, string.find(s, date)))    --> 30/05/1999

s = "hello world from Lua"

for w in string.gmatch(s, "%a+") do

         print(w) –可以理解为匹配到一次之后,继续再匹配

           --string.match就只匹配一起

end

string.gsub("hello, up-down!", "%A", ".") 表示把任何非字母的字符替换为点号.

*和-长匹配短匹配的差别

test = "int x; /* x */ int y; /* y */"

print(string.gsub(test, "/%*.*%*/", "<COMMENT>"))

    输出--> int x; <COMMENT>

然而模式 '.-' 进行的是最短匹配,她会匹配 "/*" 开始到第一个 "*/" 之前的部分:

test = "int x; /* x */ int y; /* y */"

print(string.gsub(test, "/%*.-%*/", "<COMMENT>"))

    输出--> int x; <COMMENT> int y; <COMMENT>

闭包

先看一个例子

function bibao()

         local var = 0

         function _subfunc()

                   var = var + 1

                   print("var: "..var)

                   return var

         end

         return _subfunc

end

f = bibao()

f()

f()

输出是1, 2

function bibao(var)

         --local var = 0

         function _subfunc()

                   var = var + 1

                   print("var: "..var)

                   return var

         end

         return _subfunc

end

f = bibao(2)

f()

f()

输出是3,4

这里变量var对于_subfunc而言,既不是全局变量,也不是局部变量,但又能被访问到,这个变量叫upvalue,upvalue实际指的是变量而不是值,这些变量可以在内部函数之间共享

定义: 闭包是一个函数加上它可以正确访问的 upvalues,这个函数一般是一个匿名函数,并且定义在另一个函数内部;这个函数可以访问定义在外部函数内的成员变量,参数,以及全局函数

闭包应用场景:

1 作为函数的参数,比如gsub第三个参数可以指定一个function

2 创建一个函数,即函数返回一个函数

3 函数hook,比如io.open这个替换为我们的函数,保存老的函数做一些文件权限的检查

4 实现迭代器,每个迭代器都需要在每次成功调用之间保持一些状态,这样才能知道它所在的位置及如何进到下一个位置。闭包刚好适合这种场景

迭代器

利用闭包实现的一个简单迭代器

function iter(t)

         local pos = 0

         local maxn = table.getn(t)

         function get_item()

         pos = pos + 1

         if(pos <= maxn) then

         return t[pos]

         end

         return nil

         end

         return get_item

end

t = { "1sysnap", "2jim", "3green"}

for k,_ in iter(t)

do

         print(k)

end

local it = iter(t)

local item = nil

while true

do

         item = it()

         if(item == nil) then

                   break

         end

         print(item)

end

元表

背景:

改变table的行为,每个行为关联了对应的元方法。比如俩个表相加

当Lua试图对两个表进行相加时,先检查两者之一是否有元表,之后检查是否有一个叫"__add"的字段,若找到,则调用对应的值。"__add"等即时字段,其对应的值(往往是一个函数或是table)就是"元方法"

__index元方法例子:

t = { ["name"] = "sysnap"}

print(t["name"])

也可以写为t = { name = "sysnap"}

print(t.name)

再看一个元表的例子

t = { name = "sysnap", ["foo"] = 2}

mt = {}

mt.__index = t

newt = setmetatable({}, mt )

--newt = setmetatable({}, {__index = t})

print(newt.name, newt["foo"])

Lua查找一个表元素时的规则,其实就是如下3个步骤:

1.在表中查找,如果找到,返回该元素,找不到则继续

2.判断该表是否有元表,如果没有元表,返回nil,有元表则继续。

3.判断元表有没有__index方法,如果__index方法为nil,则返回nil;如果__index方法是一个表,则重复1、2、3;如果__index方法是一个函数,则返回该函数的返回值。

t = { name = "sysnap", ["foo"] = 2}

function newd(tb, key)

         print("key: ", key)

         return t[key]

end

mt = {}

mt.__index = newd

newt = setmetatable({}, mt )

print(newt.name, newt["foo"])

__tostring元方法例子: 控制表的输出

function printTable(t, n)

         if "table" ~= type(t) then

                   return 0;

         end

         n = n or 0;

         local str_space = "";

         local str_return = "";

         for i = 1, n do

                   str_space = str_space.."  ";

         end

         str_return = (str_space.."{ ");

         for k, v in pairs(t) do

                   local str_k_v = str_space.."  ["..tostring(k).."] = ";

                   if "table" == type(v) then

                            str_return = str_return..str_k_v.." ";

                            printTable(v, n + 1);

                   else

                            str_k_v = str_k_v..tostring(v);

                            str_return = str_return..str_k_v.." ";

                   end

         end

         str_return = str_return..str_space.."}";

         return str_return

end

tb = { name = "sysnap", ["foo"] = 2}

setmetatable(tb, {__tostring = printTable})

print(tb)

__call元方法: 类似C++的仿函数

t = { name = "sysnap", ["foo"] = 2}

t.__call = function (self, arg1) –因为是.访问,第一个参数是表本身,如果没传递参数这--里都可以直接为空

         print("hello table!"..arg1)

end

setmetatable(t, t)

print(t(1))

面向对象

.调用函数: 句号要显示传递或接收self参数

tb = { data1 = "hello", data2 = "world"}

function tb.hello(self)

         print("hello world"..self.data1)

end

tb.hello(tb)

:调用函数: 冒号默认传自己为参数,通过self关键字访问

tb = { data1 = "hello", data2 = "world"}

function tb:hello() –这里如果不用:是没办法用self关键字的

         print("hello world"..self.data1)

end

tb:hello()

模块

Lua 5.1提供了一个新函数module,囊括了上面一系列定义环境的功能。在开始编写一个模块时,可以直接用module("modname", package.seeall)来取代前面的设置代码。在一个模块文件开头有这句调用后,后续所有代码都不需要限定模块名和外部名字,同样也不需要返回模块table

原文地址:https://www.cnblogs.com/sysnap/p/5681655.html