当前位置:网站首页>require、loadfile、dofile、load、loadstring
require、loadfile、dofile、load、loadstring
2022-07-27 21:24:00 【森明帮大于黑虎帮】
1.loadfile只编译,不运行loadfile(filename, mode, env) 用于加载一个指定路径filename的代码块,参数如下:
基本和load等同,区别是用来加载一个文件的代码块,参见如下:
LuaFunc.lua(被访问)文件:
--LuaFunc.lua
function add(x, y)
return x + y
end
m = "LuaFunc.m"
local n = "n"
print("------------------ < LuaFunc.lua > ------------------")
print("m = "..m)
print("n = "..n)
print("------------------ < LuaFunc.lua > ------------------")
调用代码如下:
--加载并编译代码
f = assert(loadfile("Child/LuaFunc.lua"))
--运行
f()
print("add : "..add(100, 88))
print(m)
输出结果如下:
------------------ < LuaFunc.lua > ------------------
m = LuaFunc.m
n = n
------------------ < LuaFunc.lua > ------------------
add : 188
LuaFunc.m
loadfile:只编译,不运行,它只会加载文件,编译代码,不会运行文件里的代码,loadfile只会加载(load)lua文件但是不会执行(run)。比如,我们有一个hellofile.lua文件:
print(“hello”);
function hehe()
print(“hello”);
end
这个文件里有一句代码,和一个函数。试试用loadfile加载这个文件,如下代码:
loadfile("hellofile.lua");
print("end");
输出结果如下:
end
如果说loadfile会执行文件里的代码的话,那么,应该会输出hello字符串的。结果表明,它是不会执行代码的。
2.dofile执行dofile(filename) 用于加载一个指定路径filename的代码块,并运行。参数如下:
内部先调用了loadfile,然后会自动运行一下,参见如下:
dofile("Child/LuaFunc.lua")
print("add : "..add(100, 88))
print(m)
输出与上例等同。
- 执行
dofile就是执行代码,dofile与require类似,但是它没有caching已经执行过一次的文件,所以它可以重复执行多次。很明显,dofile就是会执行代码的家伙了,如下代码:
dofile("D:/vscode lua代码/hello world/foo.lua");
print("end");
输出结果如下:
hello
end
3.require我只执行一次
require(modname) 用于加载一个指定的代码块,并运行。参数如下:
这个函数对于同一个代码块只会加载一次(加载过会保存起来),和dofile类似,加载编译后也会自动运行,参见如下:
--加载编译并运行
require("Child/LuaFunc") -- 等同于:require("Child.LuaFunc")
print("add : "..add(100, 88))
print(m)
输出与上例等同。
require和dofile有点像,不过又很不一样,require在第一次加载文件的时候,会执行里面的代码。但是,第二次之后,再次加载文件,则不会重复执行了。换句话说,它会保存已经加载过的文件,不会重复加载。require的返回值会被存储cache起来,所以一个文件最多只会执行一次,即使被require很多次。
for i = 1, 2, 1 do
require("foo.lua");
end
print("end");
为了说明这种情况,我刻意调用了两次require,输出结果如下:
hello
end
和我们说的一样,调用了两次,但是代码只执行了一次。如果这里换成dofile,则会输出两次hello字符串。
4.load用于加载字符串代码块
同loadstring,5.2版本之后loadstring被移除,用load代替,load(chunk, chunkname, mode, env) 用于加载字符串代码块,参数如下:
这里要注意:load用于加载字符串代码块并编译,但是并没有运行。在使用前要记得运行一下,参见如下:
a = 100
--加载字符串代码块
f = assert(load("a = a + 100"))
print("before a = "..a)
--运行代码块
f()
print("after a = "..a)
输出结果如下:
before a = 100
after a = 200
可以看到加载代码块后,在没有运行前,a的值没有发生变化为100,运行后执行了a = a + 100,a = 200。
5.代码块chuck如何理解lua中的代码块chunk,实际编译的时候,相当于被一个可变参匿名函数包装,并且会绑定一个唯一的upvalue值_ENV,运行后将代码块chunk中的全局变量添加到了全局环境变量_ENV中。代码块 “a = a + 100” 相当于如下函数:
--代码块
function chuck()
a = a + 100
end
--这句是比喻load代码块的加载编译过程(不一定恰当,意会就好)
f = chuck()
--运行
f()
这里有些时候可能会疑惑,load中的这段代码块为什么能访问到外部的变量a?
env:它是一个环境变量,可以自定义(一般用于模拟一个沙盒环境),默认这个值会用lua的全局环境变量_ENV填充。
_ENV是lua5.2版本才有的用来代替_G的一个全局变量(_ENV内部是指向_G的,可以简单的认为他们是同一个东西),但它是一个upvalue值。(_G及_ENV感兴趣的可以自行了解)这里简单描述一下_ENV,每一个lua代码块默认都会有一个_ENV全局环境变量,它是一个表,包含了所有的lua标准类库及所有编译过的全局变量。
a = 100
--加载并运行字符串代码块
assert(load("a = a + 11; b = 'b126'; print('this is chunk')"))()
print("a = "..a)
print("_ENV.a = ".._ENV.a)
print("b = "..b)
print("_ENV.b = ".._ENV.b)
输出如下:
this is chunk
a = 111
_ENV.a = 111
b = b126
_ENV.b = b126
可以看到:
代码块中,可以调用
print函数,这就是因为默认env传入的是_ENV,相当于调用_ENV.print。a和_ENV.a输出相同,其实在编译的时候,全局变量默认都会在前面加一个_ENV.限定。编译并运行代码块
chunk后,变量b已被加入到_ENV中。
自定义环境变量env的使用:一般用于模拟一个沙盒环境,参见如下:
a = 100
--自定义环境变量
local env = {
a = 8,
print = print
}
--加载并运行字符串代码块
assert(load("a = a + 10; print('this is chunk, a = '..a)", "chunkTest", "bt", env))()
print("a = "..a)
输出如下:
this is chunk, a = 18
a = 100
可以看到代码块
chunkTest中,a取的是自定义环境变量env的a值,打印a = 18;因为这里没有用默认全局环境变量
_ENV填充,所以外部变量a并没有被修改:a = 100env中的 print = print,等价于:print = _ENV.print。
边栏推荐
- How to use C WinForm to copy files and display progress
- [roarctf2019] babyrsa Wilson theorem
- Redefine analysis - release of eventbridge real-time event analysis platform
- 【zer0pts CTF 2022】 Anti-Fermat
- BUUCTF-RSA4
- 29. Learn the stacked column chart of highcharts using percentage
- [极客大挑战 2019]RCE ME
- Sum of factorials of Luogu p1009 [noip1998 popularization group]
- Comparison between virtual memory and cache
- Buuctf childrsa Fermat theorem
猜你喜欢

xss.haozi.me练习通关
![[gwctf 2019] boring lottery](/img/ea/34567ad06fae524bd685a26a6d4899.png)
[gwctf 2019] boring lottery

4小时定单破20000+,自称“百万内最豪华”,国产品牌飘了?

Explain the idempotence of distributed system in detail

How Flink uses savepoint

基于原生js实现今日新闻网站

What is the prospect of low code development? Are you really optimistic about low code development?

传奇外网架设教程带图文解说——Gom引擎
![[unity] mapping 2D coordinates to ID](/img/e8/e6e56ba63dd56009bfabe647f2e3ed.png)
[unity] mapping 2D coordinates to ID

2022 summer vacation daily question (5)
随机推荐
Smartrefresh nested multiple recycleview sliding conflicts and incomplete layout display
2022 International Conference on civil, building and Environmental Engineering (iccaee 2022)
[MRCTF2020]babyRSA
荣耀多款产品齐发,笔记本MagicBook V 14售价6199元起
[gwctf 2019] boring lottery
蚁剑常见报错
The 4-hour order exceeds 20000+, claiming to be "the most luxurious in a million". Is the domestic brand floating?
Arm32进行远程调试
网站被黑后处理方法及删除批量恶意代码的方法步骤
[NPUCTF2020]EzRSA
TCP的粘包拆包问题+解决方案
【zer0pts CTF 2022】 Anti-Fermat
UE4官方AEC蓝图案例课程学习笔记
解密 OOM 崩溃下降 90% 的秘密~
The interviewer asked the thread safe list, and I'm not afraid after reading it!
CPU的控制方式
BUUCTF-RSA roll
What is the prospect of low code development? Are you really optimistic about low code development?
Why does redis cluster use reverse proxy? Just read this one
【C语言】字符串逆序(递归实现)