Lua是一种轻量级、高效的脚本语言,由巴西里约热内卢天主教大学(PUC-Rio)的Roberto Ierusalimschy、Waldemar Celes和Luiz Henrique de Figueiredo于1993年开发。Lua在葡萄牙语中意为"月亮",象征着其简洁、优雅的设计理念。
了解Lua的发展历程有助于理解其设计理念:
Lua的安装非常灵活,可以根据不同的使用场景选择合适的安装方式。了解不同安装方式的原理有助于更好地使用Lua。
方法1:预编译版本(推荐新手)
方法2:使用包管理器(推荐开发者)
# 使用Chocolatey
choco install lua
# 使用Scoop
scoop install lua
# 使用Homebrew(推荐)
brew install lua
# 安装特定版本
brew install lua@5.3
# 安装LuaRocks包管理器
brew install luarocks
# Ubuntu/Debian
sudo apt update
sudo apt install lua5.4
# CentOS/RHEL/Fedora
sudo yum install lua # 或 sudo dnf install lua
# Arch Linux
sudo pacman -S lua
# 从源码编译(最新版本)
wget https://www.lua.org/ftp/lua-5.4.6.tar.gz
tar zxf lua-5.4.6.tar.gz
cd lua-5.4.6
make linux test
sudo make install
安装完成后,验证Lua是否正常工作:
# 检查版本
lua -v
# 输出: Lua 5.4.x Copyright (C) 1994-2023 Lua.org, PUC-Rio
# 测试简单脚本
echo "print('Hello Lua!')" > test.lua
lua test.lua
# 输出: Hello Lua!
Lua解释器的核心是一个轻量级的虚拟机,它负责解析和执行Lua字节码。安装过程主要包括:
让我们从经典的"Hello World"程序开始,理解Lua程序的基本结构和执行流程。
使用文本编辑器创建 hello.lua 文件:
-- 这是单行注释
-- Lua程序从第一行开始执行
-- print函数用于向标准输出打印文本
print("Hello, Lua!")
print("欢迎来到Lua的世界!")
-- 程序执行完毕,自动退出
在命令行中执行:
# 方式1:直接运行脚本文件
lua hello.lua
# 方式2:使用shebang(Unix/Linux/macOS)
# 在文件第一行添加:#!/usr/bin/env lua
# 然后给文件添加执行权限:chmod +x hello.lua
# 最后直接运行:./hello.lua
# 方式3:将代码作为参数传递给lua解释器
lua -e "print('Hello from command line!')"
print是Lua标准库中的一个基础函数,它的工作原理:
-- print函数可以接受多个参数,用逗号分隔
print("姓名:", "张三", "年龄:", 25)
-- 输出不同类型的数据
print("字符串:", "Hello")
print("数字:", 42)
print("布尔值:", true)
print("nil值:", nil)
-- print函数会自动在参数间添加制表符,末尾添加换行符
print("第一行")
print("第二行")
print函数实际上是通过C API实现的,它:
Lua提供了强大的交互式环境(Read-Eval-Print Loop,REPL),非常适合学习、测试和调试代码。
在命令行中直接输入 lua 即可进入交互模式:
$ lua
Lua 5.4.6 Copyright (C) 1994-2023 Lua.org, PUC-Rio
> print("Hello Lua!")
Hello Lua!
> print(2 + 3)
5
> print("2" + "3") -- 字符串自动转换为数字
5.0
> os.exit() -- 退出交互模式
-- 定义变量和函数
> name = "张三"
> age = 25
> function greet(person, years)
>> return "你好," .. person .. ",你今年" .. years .. "岁"
>> end
-- 使用定义的函数
> print(greet(name, age))
你好,张三,你今年25岁
-- 数学计算
> x = 10
> y = 20
> print("x + y =", x + y)
x + y = 30
-- 查看变量类型
> print(type(name))
string
> print(type(age))
number
> print(type(greet))
function
-- 多行代码块(使用do...end)
> do
>> local temp = "临时变量"
>> print(temp)
>> end
临时变量
> print(temp) -- 临时变量已超出作用域
nil
-- 方式1:使用os.exit()函数
> os.exit()
-- 方式2:使用Ctrl+D(Unix/Linux/macOS)
-- 方式3:使用Ctrl+Z然后Enter(Windows)
-- 方式4:使用EOF(End of File)信号
-- 在空行按Ctrl+D(Unix)或Ctrl+Z(Windows)
交互式模式实际上是一个循环程序,它:
每次输入的代码都在同一个Lua状态(Lua state)中执行,因此变量和函数定义会保持。
Lua的语法设计非常简洁,但理解其背后的原理对于编写高质量的代码至关重要。
-- 这是单行注释
--[[
这是多行注释
可以跨越多行
注释内容不会被解释器执行
]]
--[[
嵌套注释示例(Lua 5.0+)
--[[
内部注释
]]
]]
-- 重新启用代码的快捷方式
--[[
print("这行代码被注释掉了")
--]]
--- 恢复执行
print("这行代码会执行")
在词法分析阶段,注释会被完全忽略,不会生成任何字节码。这有助于:
Lua语句可以以分号结尾,但不是必须的:
-- 以下写法都是合法的
print("Hello")
print("Hello");
-- 多个语句在同一行时,分号是必须的
print("First"); print("Second")
-- 但不建议这样写,应该每行一个语句
print("First")
print("Second")
-- 合法的标识符
name = "张三"
_age = 25
firstName = "李"
MAX_SIZE = 100
_private_var = "内部使用"
-- 非法的标识符(会导致语法错误)
-- 1stName = "错误" -- 不能以数字开头
-- first-name = "错误" -- 不能包含连字符
-- first name = "错误" -- 不能包含空格
-- 关键字不能用作标识符
-- and = 1 -- 错误:and是关键字
-- local = 2 -- 错误:local是关键字
| and | break | do | else | elseif |
| end | false | for | function | goto |
| if | in | local | nil | not |
| or | repeat | return | then | true |
| until | while |
Lua使用do...end来创建代码块,这会影响变量的作用域:
-- 全局变量(在整个程序中有效)
globalVar = "我是全局变量"
-- 代码块
local blockVar = "我是块级变量"
print(blockVar) -- 可以访问
end
-- print(blockVar) -- 错误:blockVar已超出作用域
print(globalVar) -- 可以访问全局变量
Lua是大小写敏感的语言:
name = "张三"
Name = "李四"
NAME = "王五"
print(name) -- 输出:张三
print(Name) -- 输出:李四
print(NAME) -- 输出:王五
-- 这三个是不同的变量
print(name == Name) -- 输出:false
Lua的语法设计体现了"简单即美"的理念:
通过以下示例,我们将深入理解Lua的基本概念和编程思想。
-- 多行注释示例
--[[
文件名:demo.lua
作者:张三
描述:Lua基础语法演示
创建时间:2024年1月
]]
-- 变量定义和输出
local name = "李四"
local age = 30
local height = 175.5
local isStudent = false
print("=== 个人信息 ===")
print("姓名:", name)
print("年龄:", age)
print("身高:", height, "厘米")
print("是否学生:", isStudent)
-- 数学运算
local a = 15
local b = 7
print("\n=== 数学运算 ===")
print("a + b =", a + b)
print("a - b =", a - b)
print("a * b =", a * b)
print("a / b =", a / b)
print("a % b =", a % b) -- 取模运算
print("a ^ 2 =", a ^ 2) -- 幂运算
-- 字符串操作
local greeting = "你好"
local punctuation = "!"
print("\n=== 字符串操作 ===")
print("完整问候:", greeting .. " " .. name .. punctuation)
print("字符串长度:", #name) -- #操作符获取字符串长度
print("字符串重复:", string.rep("-", 20)) -- 重复字符
-- 布尔运算
local x = true
local y = false
print("\n=== 布尔运算 ===")
print("x and y:", x and y)
print("x or y:", x or y)
print("not x:", not x)
-- 类型检查
print("\n=== 类型检查 ===")
print("name的类型:", type(name))
print("age的类型:", type(age))
print("isStudent的类型:", type(isStudent))
print("nil的类型:", type(nil))
从Lua 5.3开始,数值系统引入了整数和浮点数的明确区分:
-- 数值类型演示
print("\n=== 数值类型演示 ===")
-- 整数
local intNum = 42
print("整数:", intNum, "类型:", type(intNum))
-- 浮点数
local floatNum = 3.14
print("浮点数:", floatNum, "类型:", type(floatNum))
-- 科学计数法
local sciNum = 1.5e3 -- 1500
print("科学计数法:", sciNum)
-- 数值运算的类型转换
local result1 = 10 + 5.5 -- 整数 + 浮点数 = 浮点数
local result2 = 7.0 * 3 -- 浮点数 * 整数 = 浮点数
print("10 + 5.5 =", result1, "类型:", type(result1))
print("7.0 * 3 =", result2, "类型:", type(result2))
-- 除法总是返回浮点数
print("10 / 3 =", 10 / 3) -- 3.333...
print("10 // 3 =", 10 // 3) -- 整数除法:3
-- 字符串特性演示
print("\n=== 字符串特性 ===")
-- 字符串字面量的多种写法
local str1 = '单引号字符串'
local str2 = "双引号字符串"
local str3 = [[多行
字符串]]
local str4 = [=[包含[[]]的字符串]=] -- 长括号语法
print(str1)
print(str2)
print(str3)
print(str4)
-- 转义字符
local escaped = "换行符:\n制表符:\t引号:\"反斜杠:\\"
print("转义字符:", escaped)
-- 字符串是不可变的
local original = "Hello"
local modified = original .. " World"
print("原始字符串:", original) -- 仍然是"Hello"
print("修改后字符串:", modified) -- 新的字符串"Hello World"
nil在Lua中具有特殊的地位:
-- nil值演示
print("\n=== nil值演示 ===")
-- 未定义的变量
print("未定义变量:", undefinedVar) -- 输出: nil
-- 给变量赋nil
local temp = "临时值"
print("赋值前:", temp)
temp = nil
print("赋值nil后:", temp) -- 输出: nil
-- nil在条件判断中的行为
if nil then
print("nil被视为true") -- 不会执行
else
print("nil被视为false") -- 会执行
end
-- 检查变量是否存在
if someUndefinedVar == nil then
print("变量someUndefinedVar不存在")
end
完成以下练习题,确保你真正理解了本课的内容。建议按顺序完成,每个练习都设计有特定的学习目标。
lua -v2^10, 100 // 3, math.pitype()函数检查不同值的类型personal_info.lua文件math.pi作为圆周率"10" + 5, "10" .. 5, 10 .. "5"tonumber()和tostring()函数的作用os.clock()函数测试不同操作的执行时间