zoukankan      html  css  js  c++  java
  • http://www.runoob.com/lua/lua-basic-syntax.html

    Lua优点及特性

    1. Lua 是一个小巧的脚本语言。 其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能。Lua由标准C编写而成,几乎在所有操作系统和平台上都可以编译,运行。Lua并没有提供强大的库,这是由它的定位决定的。Lua 有一个同时进行的JIT项目,提供在特定平台上的即时编译功能。

    2. Lua脚本可以很容易的被C/C++ 代码调用,也可以反过来调用C/C++的函数,这使得Lua在应用程序中可以被广泛应用。不仅仅作为扩展脚本,也可以作为普通的配置文件,代替XML,ini等文件格式,并且更容易理解和维护。 Lua由标准C编写而成,代码简洁优美,几乎在所有操作系统和平台上都可以编译,运行。一个完整的Lua解释器不过200k,在目前所有脚本引擎中,Lua的速度是最快的。

    在开始学习之前,先介绍一些最基本的概念,在Lua中具有一个代码块的概念,每个函数或者for循环等都是一个代码块。在Lua中,用 “- - ”来标记该行的注释,使用“- - [ [” 和   “ - - ] ] ”之间括起来的部分进行块注释。如下所示:

    1
    2
    3
    4
    5
    6
    7
    -- 行注释,仅仅注释当前行  
    for idx = 1, 10 do  --在代码之后进行行注释  
         print("idx=",idx);    
    end  
    --[[  
    块注释,上边的for循环结构跟end结合起来就是一个Lua中常见的代码块结构。  
    --]]

    另外,Lua中支持的算术运算符有:+、-、*、/,即加、减、乘、除;支持的关系运算符有:==、~=(不等于)、<、>、<=、>=;支持的逻辑运算符有:and、or、not。需要注意的是,在Lua中,and逻辑运算符如果第一个参数是false,则返回false,不会执行第二个参数的代码(即使第二个参数是一个错误的表达式,也能顺利运行);如果第一个参数是true,返回第二个参数的值。 同理,or逻辑运算符如果第一个参数不是false,则返回第一个参数的值(不会执行第二个参数的代码);否则返回第二个参数的值。这就是所谓的逻辑运算符短路求值。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    result = true  
    if result and an_donot_defined_method() then  
      print("no erro occured!")  
    end  
    --[[  
    上述代码输出的错误如下:  
    stdin:1: attempt to call global 'an_donot_defined_method' (a nil value)  
    stack traceback:  
        stdin:1: in main chunk  
        [C]: ?  
    --]]  
    result =false   
    if (result and an_donot_defined_method())==false  then  
      print("no erro occured!")  
    end  
    --上述代码顺利通过编译,即使有一个没定义的方法,打印结果:no erro occured!

    一、基本数据类型

    Lua中具有5种基本的数据类型:nil、Boolean、string、Number和table。在Lua中使用变量不需要提前声明,变量的类型决定于用户赋值的类型。可以使用 type()函数判断变量的类型。其中,nil、Boolean、Number都是用法比较简单的类型,string、table类型用法稍微复杂点。给一个变量赋值为nil,表示释放该变量。Boolean跟其他语言一样,只有true和false两种值。Number是双精度浮点数,Lua中没有整数类型。table类型可以当作数组使用。

    在Lua中,变量默认是全局的,这通常导致一些调试困难,最好尽量显式的在变量名之前加上 local 关键字声明该变量为局部变量。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    gNumber = 10  --这是一个默认全局的变量  
    print(type(gNumber))  
    --输出结果为number  
    gNumber = nil --之前的number类型gNumber = 10变量被释放  
    print(type(gNumber))  
    --输出结果为nil  
       
    function LocalVarFunction ()  
      local pTable = {} --用local关键字声明一个局部变量,这个变量将在执行LocalVarFunction方法后销毁  
         for idx = 1, 5 do   
               local result = true  --这个result将在每个for循环执行之后销毁  
               if result then   
                  local pString = "这个字符串将在if代码块之后销毁"  
                  pTable[idx] = pString  
                  print(pTable[idx])  
               end  
         end  
    end

    下面详细介绍string以及table两种类型的详细用法。

    1、string类型的用法

    Lua中的字符串操作非常出色。下表是一些特殊意义的字符:

    特殊的Lua字符串

    QQ截图20141121173412.png

    a、类型转换

    Lua会根据上下文在合理合法的情况下隐式进行数字和字符之间的转换。另外,也可以使用tonumber()函数和tostring()函数显式地进行字符与数字的转换。 见代码实例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    --字符与数字的隐式转换  
    print("10" + 7)  
    --输出结果为:17,将字符10隐私转化为Number类型计算  
    print("hello" + 7)  
    --无法进行运算,即不能隐式将"hello"字符转化为Number计算  
    --[[  
       系统错误如下:  
    stdin:1: attempt to perform arithmetic on a string value    
    stack traceback:    
        stdin:1: in main chunk    
        [C]: ?    
    --]]  
       
       
       
    --字符与数字的显式转换  
    print(tonumber("100")+11)  
    --输出结果为:111  
    print(type(tostring(100)))  
    --输出结果为:string

    b、常用的字符处理函数介绍    

    • string.char()函数根据传入的ASCII编码返回该编码对应的字符。如:string.char(10),表示字符换行符,10是换行符的ASCII编码。

    • string.len()函数求字符串的长度。如:

    1
    2
    print(string.len("hello"))  
    --输出结果为:5
    • string.sub(aString, start, end) 函数返回指定字符串的子串。如:

    1
    2
    3
    gString = "hello Lua"  
    print(string.sub(gString, 7,9))  
    --输出结果为:Lua
    • string.format()函数格式化输出指定字符串。%s表示字符串,%d表示所有数字,%D表示非数字,%a表示字母,%c表示控制字符,%l小写字母,%p标点符号,%s空格符号,%u大写字母,%w字母数字,%x十六进制数,%z用0表示的字符。加%前缀可以让特殊符号也能用在格式化中(如:().%+_*?[ ^ $ ]),如%%代表百分比符号。%.4f表示小数点后有4位的浮点数,d.表示至少有两个数字的整数,如果不足两个数字则用0补足。如:

    1
    2
    3
    4
    aString = "哈哈,你是"  
    bString = "一头猪"  
    print(string.format("%s%s", aString, bString))  
    --输出结果为:哈哈,你是一头猪
    • sting.find(sourceString, targetString) 函数在sourceString字符串中查找第一个符合targetString字符串的位置,如果找到则返回开始和结束的位置,没找到则返回nil。

    • string.gsub(sourceString, pattern, replacementString) 函数返回一个字符串,sourceString字符中满足pattern格式的字符都会被替换成replacementString参数的值。

    • string.gfind(sourceString, pattern) 函数遍历一个字符串,一旦查找到符合指定格式的字符串就返回该子串。

    2、table类型的用法

    一般table可以当做数组使用,可以通过table[n]的索引形式访问任意数组中的某个成员。在Lua中,table还能被当做字典dictionary数据使用,并且数组跟字典的用法还能混合使用(实质上还是数组,只不过索引从数字变成其他属性值)。

    a、使用其他值作为table的索引以及多维table

    table还可以使用其他的值作为索引值,并且能用数字跟其他值同时作为同一个table的索引。如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    gTable = {}  
    gTable.name = "eric"  
    gTable.gender = "man"  
    gTable.phonenumber = "0000000000"  
    gTable[1] = "公司"  
    gTable[2] = "部门"  
    for index, value in pairs(gTable) do   
      print(index, value)  
    end  
    --[[  
    输出结果如下:  
    1   公司  
    2   部门  
    phonenumber 0000000000  
    gender  man  
    name    eric  
    --]]

    注意,上述循环中的pairs()函数可以遍历table中的每一对值(索引以及索引对应的value,有点类似字典,不是吗?)

    事实上,table的索引还可以是table本身,这样就组成了一个多维table或多维字典。跟其他语言的多维数组或字典比起来,使用真是超级方便,非常非常的灵活。如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    gTable = {}  
    gTable.name = "eric"  
    gTable.gender = "man"  
    gTable.phonenumber = "0000000000"  
    gTable[1] = "公司"  
    gTable[2] = "部门"  
    gTable.hobby = {"跑步""读书""游戏""动漫"}  -- 多维table,可以通过gTable.hobby[1]的方式访问.即gTable.hobby本身也是一个table  
    gTable.secTable = {}  
    gTable.secTable.job = "程序员"  
    gTable.secTable.label = "写代码的"  
    gTable.secTable.description = "职责是实现产品的逻辑"  
       
    for index, value in pairs(gTable) do   
      print(index, value)  
      if ("table" == type(value)) then  
         for idx, var in pairs(value) do   
             print("二维table:", idx, var)  
         end  
       end  
    end  
    --[[  
    输出结果如下:  
    1   公司  
    2   部门  
    hobby   table: 0x7fdceac14bc0  
    二维table:    1   跑步  
    二维table:    2   读书  
    二维table:    3   游戏  
    二维table:    4   动漫  
    phonenumber 0000000000  
    gender  man  
    secTable    table: 0x7fdceac15100  
    二维table:    label   写代码的  
    二维table:    description 职责是实现产品的逻辑  
    二维table:    job 程序员  
    name    eric  
    --]]

    b、table 的常用函数

    • table.getn()函数,返回table中元素的个数。如:

    1
    2
    3
    4
    gStringTable = {"a""b","c","d","e"}  
    for i = 1, table.getn(gStringTable) do  
         print(gStringTable[i])  
    end
    • table.sort()函数,将table中的元素从小到大排列。如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    gNumberTable = {10, 5, 7, 2,3, 2}  
    table.sort(gNumberTable)  
    for i = 1, table.getn(gNumberTable) do   
       print(gNumberTable[i])  
    end  
    --输出结果如下:  
    2  
    2  
    3  
    5  
    7  
    10
    • table.insert(pTable, position, value) 函数在table中插入一个新值,位置参数如果没指定,则默认将新值插入到table的末尾。

    • table.remove(pTable, position) 函数从指定table中删除指定位置的元素并返回该元素,如果没有指定删除的位置,则默认删除table的最后一个元素。

    介绍到这里, Lua中基本的数据类型诸位应该都能掌握,休息一下,下面接着开始简单介绍Lua的基本语句以及函数。

    二、Lua中的常用语句结构以及函数

    1、Lua中的常用语句结构介绍

    1
    2
    3
    4
    5
    6
    7
    8
    9
    --if 语句结构,如下实例:  
    gTable = {"hello", 10}  
    if nil ~= gTable[1] and "hello" == gTable[1] then  
      print("gTable[1] is" , gStringTable[1])  
    elseif  10 == gTable[2] then  
      print("gTable[2] is", gTable[2])  
    else   
      print("unkown gTable element")  
    end
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    --while 和repeat循环语句结构,while先判断条件,如果true才执行代码块(有可能跳过该代码块);repeat则是在最后判断条件,保证代码块至少执行一次。  
    gTable = {1,2,3,4,5,6,7,8,9,10}  
    index = 1  
    while gTable[index] < 10 do   
       print("while gTable[",index,"] is ",gTable[index])  
       index = index + 1 -- 注意,Lua不支持index++或者index += 1形式的运算符。  
    end  
    --[[  
    while循环输出结果如下:  
    while gTable[   1   ] is    1  
    while gTable[   2   ] is    2  
    while gTable[   3   ] is    3  
    while gTable[   4   ] is    4  
    while gTable[   5   ] is    5  
    while gTable[   6   ] is    6  
    while gTable[   7   ] is    7  
    while gTable[   8   ] is    8  
    while gTable[   9   ] is    9  
    --]]  
       
    --上一个循环结束后,index = 10  
    repeat  
        print("repeat gTable[",index,"] is ",gTable[index])  
       index = index - 2  
    until index < 1  
    --[[  
    输出结果如下:  
    repeat gTable[  10  ] is    10  
    repeat gTable[  8   ] is    8  
    repeat gTable[  6   ] is    6  
    repeat gTable[  4   ] is    4  
    repeat gTable[  2   ] is    2  
    --]]
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    --for循环结构,for循环结构具有三个参数,初始值,结束值,每个循环增加值。  
    for index = 1, 5 do --不设置第三个参数的话,默认缺省第三个参数是1,即每个循环 index 增加1  
       print("for cycle index =",index)  
    end  
    --[[  
    输出结果为:  
    for cycle index =   1  
    for cycle index =   2  
    for cycle index =   3  
    for cycle index =   4  
    for cycle index =   5  
    --]]  
       
    for index = 20 , 0, -5 do --设定第三个参数为-5  
     print("for cycle index:",index)  
    end  
    --[[  
    输出结果:  
    for cycle index:    20  
    for cycle index:    15  
    for cycle index:    10  
    for cycle index:    5  
    for cycle index:    0  
    --]]
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    --break关键字可以使循环强制退出,Lua中没有continue关键字,需要通过其他方式实现continue关键字,比如if-else语句。或者通过网络下载Lua的continue关键字补丁安装来解决该问题  
       
    for index = 1, 100, 5 do   
      if index > 10 and index < 25 then  --用if-else语句实现continue关键字的功能  
         print("continue!!!!! index=",index)  
      else   
        if index > 15 and index < 35 then   
           print("break~~~~~index=",index)  
           break  
        end  
        print("At end index=",index)  
      end  
    end  
       
    --[[  
    输出结果如下:  
    At end index=   1  
    At end index=   6  
    continue!!!!! index=    11  
    continue!!!!! index=    16  
    continue!!!!! index=    21  
    break~~~~~index=    26  
    --]]
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    --最后还要提的一点是,Lua中switch语句的缺失,用if-elseif-else语句代替的话,显得非常臃肿,还有其他的一些实现方案。笔者在网上麦子加菲童鞋的博客中找到一种Lua中代替switch语句非常优雅的方案。下面贴出麦子加菲原代码:  
    --Switch语句的替代语法(所有替代方案中觉得最好,最简洁,最高效,最能体现Lua特点的一种方案)  
    action = {    
      [1] = function (x) print(x) end,    
      [2] = function (x) print( 2 * x ) end,    
      ["nop"] = function (x) print(math.random()) end,    
      ["my name"] = function (x) print("fred") end,    
    }    
        
    while true do    
        key = getChar()    
        x = math.ramdon()    
        action[key](x)    
    end

    2、Lua中的函数

    在Lua脚本中,函数是以function关键字开始,然后是函数名称,参数列表,最后以end关键字表示函数结束。需要注意的是,函数中的参数是局部变量,如果参数列表中存在(...)时,Lua内部将创建一个类型为table的局部变量arg,用来保存所有调用时传递的参数以及参数的个数(arg.n)。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    function PrintTable (pTable)  
      for index = 1, table.getn(pTable) do   
          print("pTable[",index,"] =",pTable[index])  
      end  
    end  
       
    gStringTable = {"hello","how","are","you"}  
    PrintTable(gStringTable)  
    --[[  
    输出结果为:  
    pTable[ 1   ] = hello  
    pTable[ 2   ] = how  
    pTable[ 3   ] = are  
    pTable[ 4   ] = you  
    --]]  
       
    function PrintFriendInfo (name, gender, ...)   
      local friendInfoString = string.format("name:%s  gender:%d",name,gender)  
      if 0 < arg.n then  
         for index = 1, arg.n do   
            friendInfoString = string.format("%s otherInfo:%s",friendInfoString, arg[index])  
         end  
       end  
       print(friendInfoString)  
    end  
       
       
    PrintFriendInfo ("eric", 1, "程序员","2b", 50)  
       
     --输出结果为:  
    -- name:eric  gender:1 otherInfo:程序员 otherInfo:2b otherInfo:50

    Lua函数的返回值跟其他语言比较的话,特殊的是能够返回多个返回值。return之后,该Lua函数从Lua的堆栈里被清理。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    function GetUserInfo ()  
        local name = "eric"  
        local gender = 1  
        local hobby = "动漫"  
      return name, gender, hobby  
    end  
       
    print(GetUserInfo())  
       
    --输出结果:eric 1   动漫

    三、Lua中的库函数

    在本文的最后,介绍一些Lua中常用的库函数。

    1、数学库

    math库的常用函数:三角函数math.sin、math.cos、取整函数math.floor、math.ceil、math.max、math.min、随机函数math.random、math.randomseed(os.time())、变量pi和huge。

    2、I/O库

    进行I/O操作前,必须先用io.open()函数打开一个文件。io.open()函数存在两个参数,一个是要打开的文件名,另一个是模式字符,类似"r"表示读取、“w”表示写入并同时删除文件原来内容,“a”表示追加,“b”表示打开二进制文件。该函数会返回一个表示文件的返回值,如果打开出错则返回nil,写入之前需要判断是否出错,比如:local file = assert(io.open(filename, “w”))..使用完毕后,调用io.close(file).或file:close()。

    几个常用I/O函数:io.input ()、io.output ()、 io.read()、 io.write()。

    1
    2
    3
    4
    5
    local file = assert(io.open(filename, “w”))  
    if file ~= nil then  
      file:write("hello lua!!!!")  --注意,等同于io.write("hello lua!!!!")  
      file:close()  --等同于io.close(file)  
    end

    3、调试库

    • debug.getinfo()函数,他的第一个参数 可以是一个函数或一个栈层。返回结果是一个table,其中包含了函数的定义位置、行号、函数类型、函数名称等信息。

    • debug.getlocal()函数检查函数任意局部变量,有两个参数,第一个是希望查询的函数栈层,另一个是变量的索引。

    • assert(trunk)() 函数,执行参数中代码块并在出错时提供报错功能。

    1
    2
    3
    4
    5
    a = "hello world"  
    b = "print(a)"  
    assert(loadstring(b))()  
    --输出结果:  
    hello world

    4、几个处理Lua代码块的函数

    • loadstring(pString)()函数可以直接执行pString字符串组成的Lua代码,但不提供报错功能。

    1
    2
    3
    4
    5
    6
    7
    8
    loadstring("for index = 1, 4 do print("for cycle index =",index) end")()  
    --[[  
    输出结果  
    for cycle index =   1  
    for cycle index =   2  
    for cycle index =   3  
    for cycle index =   4  
    --]]
    • dofile(filename)函数的功能是载入并立刻执行Lua脚本文件。可以用来载入定义函数的文件或者数据文件、或立即执行的Lua代码。dofile函数会将程序的执行目录作为当前目录。如果要载入程序执行目录的子目录里的文件,需要加上子目录的路径。

    1
    2
    dofile("/Users/ericli/WorkSpace/Lua语言/hellolua.lua")  
    --输出结果:Hello Lua!

    本篇总结完毕,本篇只是总结了Lua的一些最基本的语法。至于Lua的更高级的内容,比如:协同程序、模块与包、Lua调用C代码、C++与Lua的整合等,还需要在以后的学习过程中深入。

    第一个 Lua 程序

    交互式编程

    Lua 提供了交互式编程模式。我们可以在命令行中输入程序并立即查看效果。

    Lua 交互式编程模式可以通过命令 lua -i 或 lua 来启用:

    $ lua -i 
    $ Lua 5.3.0  Copyright (C) 1994-2015 Lua.org, PUC-Rio
    >

    在命令行中,输入以下命令:

    > print("Hello World!")

    接着我们按下回车键,输出结果如下:

    > print("Hello World!")
    Hello World
    >

    脚本式编程

    我们可以将 Lua 程序代码保持到一个以 lua 结尾的文件,并执行,该模式称为脚本式编程,如我们将如下代码存储在名为 hello.lua 的脚本文件中:

    print("Hello World!")
    print("www.runoob.com")

    使用 lua 名执行以上脚本,输出结果为:

    $ lua test.lua
    Hello World
    www.runoob.com

    我们也可以将代码修改为如下形式来执行脚本(在开头添加:#!/usr/local/bin/lua):

    #!/usr/local/bin/lua
    
    print("Hello World!")
    print("www.runoob.com")

    以上代码中,我们指定了 Lua 的解释器 /usr/local/bin directory。加上 # 号标记解释器会忽略它。接下来我们为脚本添加可执行权限,并执行:

    ./test.lua 
    Hello World
    www.runoob.com

    注释

    单行注释

    两个减号是单行注释:

    --

    多行注释

    --[[
     多行注释
     多行注释
     --]]

    标示符

    Lua 标示符用于定义一个变量,函数获取其他用户定义的项。标示符以一个字母 A 到 Z 或 a 到 z 或下划线 _ 开头后加上0个或多个字母,下划线,数字(0到9)。

    最好不要使用下划线加大写字母的标示符,因为Lua的保留字也是这样的。

    Lua 不允许使用特殊字符如 @, $, 和 % 来定义标示符。 Lua 是一个区分大小写的编程语言。因此在 Lua 中 Runoob 与 runoob 是两个不同的标示符。以下列出了一些正确的标示符:

    mohd         zara      abc     move_name    a_123
    myname50     _temp     j       a23b9        retVal

    关键词

    以下列出了 Lua 的保留关键字。保留关键字不能作为常量或变量或其他用户自定义标示符:

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

    一般约定,以下划线开头连接一串大写字母的名字(比如 _VERSION)被保留用于 Lua 内部全局变量。


    全局变量

    在默认情况下,变量总是认为是全局的。

    全局变量不需要声明,给一个变量赋值后即创建了这个全局变量,访问一个没有初始化的全局变量也不会出错,只不过得到的结果是:nil。

    > print(b)
    nil
    > b=10
    > print(b)
    10
    >

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

    b = nil
    print(b)      --> nil

    这样变量b就好像从没被使用过一样。换句话说, 当且仅当一个变量不等于nil时,这个变量即存在。

  • 相关阅读:
    Service Name Port Number Transport Protocol tcp udp 端口号16bit
    linux linux 互传文件 win 不通过 ftp sftp 往linux 传文件(文件夹)
    soft deletion Google SRE 保障数据完整性的手段
    Taylor series
    Taylor's theorem
    Moving average
    REQUEST
    Unix file types
    mysqld.sock
    Tunneling protocol
  • 原文地址:https://www.cnblogs.com/klb561/p/8719510.html
Copyright © 2011-2022 走看看