lua基础概要

关键字

and       break     do        else      elseif
end       false     for       function  goto
if        in        local     nil       not
or        repeat    return    then      true
until     while

变量

定义全局变量
msg = "hello world"
定义局部变量
local msg = "hello world"

代码注释

行注释 --

使用 -- 可以注释到行尾

块注释 --[[]]

使用 --[[xxx]] 可以注释一个代码块

如果注释内容存在]],则需要配合=,例如--[=[会一直匹配到下一个]=]出现,]]里可以写多个=,例如--[==[会一直匹配到下一个]==].

类型

lua有8种类型,分别是:

  • Boolean
  • number
  • string
  • userdata
  • function
  • thread
  • table
type函数

使用type函数可以获取变量的类型,例如:

type(nil) --> nil
type(true) --> Boolean
type("Hello world")  --> string
type(io.stdin) --> userdata
Boolean

lua中,除了 nil 和 false 为false,其他都为true

number

lua5.3之后,number类型分为 integer 和 float
通过math.type函数可以获取number的类型,例如:

math.type(3) --> integer
math.type(3.0)   --> float

操作符

//

lua5.3加入了一个新的操作符,floor division
/运算符使用是得到一个float类型的数字,哪怕是2个integer相除
如果2个integer用//相除,会得到一个integer

关系运算符
  • <
  • >
  • <=
  • >=
  • ==
  • ~=
~=

类似其他语言的!=,和==相反.

随机数

random

使用random函数可以生成一个伪随机数
如果random不带参数,随机数分布在[0,1)中.
如果random只带一个参数,则随机数分布在[1,n]中.
如果random带2个参数,随机数分布在[n,n]中.

因为是伪随机数,所以每一次执行程序,随机数都是相同的序列,如果想改变这种情况,可以设置随机数种子,一般设置时间戳为种子.

math.randomseed

设置当前随机数种子,例如设置当前时间戳为随机数种子:

math.randomseed(os.time())

字符串

计算字符串的长度 #

# 符号用来计算字符串的长度
例如

a = "hello"
print(#a)             --> 5
拼接字符串 ...

...可以用来拼接多个字符串,例如:

"Hello " .. "World"     --> Hello World
"result is " .. 3       --> result is 3
10 .. 20                --> result is 1020
长字符串

如果一个字符串字面量,非常长,需要写多行,那么可以使用[[]]符号来创建长字符串.
例如:

page = [[
          <html>
          <head>
            <title>An HTML Page</title>
          </head>
          <body>
            <a href="http://www.lua.org">Lua</a>
          </body>
          </html>
        ]]
格式化

lua也有类似c的print函数,例如:

string.format("x = %d  y = %d", 10, 20)     --> x = 10  y = 20
string.format("<%s>%s</%s>", tag, title, tag)   --> <h1>a title</h1>

控制结构

if then else

if用来测试条件,如果为true执行then语句块,否者执行else语句块

if a < 0 then a = 0 end
if a < b then return a else return b end
if line > MAXLINES then
    showpage()
    line = 0 
end
while

while用来执行循环,条件成立则执行do语句块

local i = 1
while a[i] do
    print(a[i])
    i=i+ 1 
end
repeat

和while类似,但是第一次不测试条件,先执行后测试

local line
repeat
    line = io.read()
until line ~= ""
print(line)
Numerical for

for需要3个表达式,exp3可以省略,如果exp省略,则lua假设exp3每次+1

for var = exp1, exp2, exp3 do
    something
end
break, return, goto

break用来跳出一个循环,return用来跳出一个函数,goto可以跳到某个标签的位置,标签通过 ::xx:: 符号定义

while some_condition do
    ::redo::
    if some_other_condition then goto continue 
    else if yet_another_condition then goto redo 
    end
    some code
    ::continue::
end

Table

lua中,table是最核心的数据结构,table既不是值,也不是变量,而是一个对象.

创建table
a = {}
k = "x"
a[k] = 10
a[20] = "great"
a["x"]              --> 10
k = 20
a[k]                --> "great"
语法糖

t["name"] 在lua里 可以写成 t.name

a = {}
a.x = 10    -- same as a["x"] = 10
a.x         --> 10
构造器

{}是一个空constructor,constructor可以初始化一个列表

days = {"Sunday", "Monday", "Tuesday", "Wednesday",
                  "Thursday", "Friday", "Saturday"}
                  
print(days[4])  --> Wednesday

constructor 也可以初始化一个 record-like table

a = {x = 10, y = 20}
数组,列表,序列

一个table,如果index是一个有序序列,则这个table就是一个数组.

a = {}
a[1] = 1
a[2] = 1
a[3] = 1
a[4] = 1
数组的长度

可以和字符串一样,通过使用#来获取数组的大小

#a      --> 4
数组空洞

如果一个table的index是一个序列,但是其中某些字段为nil,那么通过#无法计算真实的数组长度

a = {}
a[1] = 1
a[2] = nil    -- does nothing, as a[2] is already nil
a[3] = 1
a[4] = 1
 
#a      --> 1
遍历table

使用 pairs iterator 可以用来迭代table

t = {10, print, x = 12, k = "hi"}
for k, v in pairs(t) do
    print(k, v)
end  
 
--> 1   10
--> k   hi
--> 2   function: 0x420610
--> x   12

pairs iterator是无序的,如果想要保持table赋值的顺序,可以使用ipairs

t = {10, print, 12, "hi"}
for k, v in ipairs(t) do
    print(k, v)
end  
 
--> 1   10
--> 2   function: 0x420610
--> 3   12
--> 4   hi

如果table是一个数组,则可以通过#符号来遍历

t = {10, print, 12, "hi"}
for k = 1, #t do
    print(k, t[k])
end
 
--> 1   10
--> 2   function: 0x420610
--> 3   12
--> 4   hi
Safe Navigation

如果我们想调用table的函数,首先得校验table是否存在.如果table嵌套比较多写起来比较丑,而且麻烦
例如:

zip = company and company.director and
          company.director.address and
                company.director.address.zipcode

使用 or {} 可以简化这种操作

zip = (((company or {}).director or {}).address or {}).zipcode

或者更简洁高效的写法

E = {}     -- can be reused in other similar expressions
zip = (((company or E).director or E).address or E).zipcode

函数

省略括号

如果函数只有一个参数,可以省略掉(),例如:

print "Hello World"     <-->     print("Hello World")
dofile 'a.lua'          <-->     dofile ('a.lua')
print [[a multi-line    <-->     print([[a multi-line
        message]]                       message]])
type{}                  <-->     type({})
实参和形参可以不对称

如果实参多余形参,则抛弃掉多余的实参,如果实参少于形参,则形参初始化为nil

function f (a, b) print(a, b) end  
  
f()             --> nil    nil
f(3)            --> nil    nil
f(3, 4)         --> 3      4
f(3, 4, 5)      --> 3      4      (5 is discarded)
多返回值

一个函数可以有多个返回值

function maximum (a)
    local mi = 1
    local m = a[mi]
    for i = 1, #a do
        if a[i] > m then
            mi = i; m = a[i]
        end 
    end
    return m, mi
end
-- index of the maximum value
-- maximum value
-- return the maximum and its index

print(maximum({8,10,23,12,5}))     --> 23   3

多返回值可以初始化一个table

print(maximum({8,10,23,12,5}))     --> 23   3       -- returns 2 results
 
t = {foo2()}        -- t = {"a", "b"}
可变参数

函数定义可以通过 ... 符号来声明可变参数

function add (...)
    local s = 0
    for _, v in ipairs{...} do
        s=s+ v 
    end
    return s 
end
 
print(add(3, 4, 10, 25, 12))    --> 54

... 甚至用来初始化变量和作为返回值

function foo (...)
    local a, b, c = ...
    
function id (...) return ... end
table.pack函数

聚合 ... 可以使用{...},也可以使用table.pack函数,{...}有可能存在空洞,而table.pack则可以检测到nil

function nonils (...)
    local arg = table.pack(...)
    for i = 1, arg.n do
      if arg[i] == nil then 
        return false 
      end
    end
    return true
end
 
print(nonils(2,3,nil))      --> false
print(nonils(2,3))          --> true
print(nonils())             --> true
print(nonils(nil))          --> false
select函数

select函数接收一个固定参数 selector,加一个可变参数,如果 selector 为n,则返回这个可变参数中n之后的参数,如果 selector#,则返回可变参数的个数
例如:

print(select(1, "a", "b", "c"))     --> a    b    c
print(select(2, "a", "b", "c"))     --> b    c
print(select(3, "a", "b", "c"))     --> c
print(select("#", "a", "b", "c"))   --> 3

通过select函数来遍历可变参数

function add (...)
    local s = 0
    for i = 1, select("#", ...) do
      s = s + select(i, ...)
    end
    return s 
end
table.unpack函数

跟table.pack函数相反,跟table.unpack函数是将一个table拆分

print(table.unpack{10,20,30})    --> 10   20   30
a,b = table.unpack{10,20,30}     -- a=10, b=20, 30 is discarded

table.unpack函数还可以接收额外的2个参数

print(table.unpack({"Sun", "Mon", "Tue", "Wed"}, 2, 3))
            --> Mon    Tue

Simple io模型

简单io模型假设存在 current input stream 和一个 current output stream
默认的current input stream 为stdin,默认的 current output stream 为stdout,io.read函数可以用来读取流里面的内容

current streams有 io.input 和 io.output 两个函数用来获取输入输出流,
例如io.input接收一个文件名,用来打开一个文件:

io.input(filename)
io.write函数

io.write可以接收任意个参数,并将它们写到current output stream

io.write(a..b..c)

一种更高效的写法(不拼接字符串)

io.write(a, b, c)
io.read函数

io.read函数从current stream中读取string,参数可以控制读取的内容

参数 内容
"a" reads the whole file
"l" reads the next line (dropping the newline)
"L" reads the next line (keeping the newline)
"n" reads a number
num reads num characters as a string
t = io.read("a")                    -- read the whole file
t = string.gsub(t, "bad", "good")   -- do the job
io.write(t)                         -- write the file

Complete I/O 模型

如果需要同时写入多个文件,则需要Complete I/O 模型,io.open用于打开一个文件,类似c里面的open
io.open函数接收一个文件名,后面加一个字符串 mode 参数,类似c,mode可以为

  • "r" 读
  • "w" 写
  • "a" 附加

如果文件不存,或者存在异常,在则返回nil

print(io.open("non-existent-file", "r"))
--> nil     non-existent-file: No such file or directory    2
 
print(io.open("/etc/passwd", "w"))
--> nil     /etc/passwd: Permission denied  13

通常检查错误是通过assert断言

local f = assert(io.open(filename, mode))

打开文件之后可以使用read和write读取或者写入,但是是在一个stream对象上操作
例如

local f = assert(io.open(filename, "r"))
local t = f:read("a")
f:close()

实际上io.read是io.input():read的简写,io.write是io.output():write的简写

预设的stream对象
  • io.stdin
  • io.stdout
  • io.stderr

直接使用预设的stream对象

io.stderr:write(message)

如果想更改current stream

local temp = io.input() io.input("newinput")    -- save current stream
do something with new input     -- open a new current stream
io.input():close()      -- close current stream
io.input(temp)      -- restore previous current stream
io.lines函数

io.lines函数返回一个重复读取文件的iterator,lua5.2之后,io.lines和io.read接收同样的参数,例如

for block in io.input():lines(2^13) do
    io.write(block)
end

执行系统命令

os.execute函数

os.execute可以执行系统命令,例如创建文件夹:

function createDir (dirname)
    os.execute("mkdir " .. dirname)
end
os.popen函数

os.popen功能和os.execute类似,但是可以获取命令的返回内容

-- for POSIX systems, use 'ls' instead of 'dir'
local f = io.popen("dir /B", "r")
local dir = {}
for entry in f:lines() do
    dir[#dir + 1] = entry
end
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,491评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,856评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,745评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,196评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,073评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,112评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,531评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,215评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,485评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,578评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,356评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,215评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,583评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,898评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,497评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,697评论 2 335

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,497评论 18 139
  • Lua 5.1 参考手册 by Roberto Ierusalimschy, Luiz Henrique de F...
    苏黎九歌阅读 13,674评论 0 38
  • ¥开启¥ 【iAPP实现进入界面执行逐一显】 〖2017-08-25 15:22:14〗 《//首先开一个线程,因...
    小菜c阅读 6,327评论 0 17
  • 这次练习忘了拍绘画过程了,因此,直接上成品照吧,下次一定记得把每一步都拍好,以便和喜欢画画的朋友们交流,本人没有学...
    眉山月阅读 3,777评论 5 4
  • 今天是18年第一天,给朋友们发了祝福,然后去买了一些必需品就回家了。感觉每天不是很累,没有想到,放松下来了,居然睡...
    786706d0f8a6阅读 160评论 0 1