2017-11-27 16:02:27 u011335616 阅读数 316

记录本人学习Lua的一些心得等。


Lua相关资料

网站

手册

安装Lua

在类Unix系统上(Linux、OSMax等等),可能已经安装了Lua,或者有可用的安装包;对于Windows可以使用LuaDist等发布的预编译包。

由于Lua开源,所以还有另外一种安装方法:通过源码安装,分构建和安装两步完成。

类Unix系统

  • 构建Lua(Build Lua)
    Lua在类Unix系统上的构建很简单,输入make + 平台名即可,如Linux平台下:
make linux
  • 安装Lua(Install Lua)
    通过以下命令即可安装至默认位置.
make install

Windows

Windows下的构建过程稍微复杂一些,看到两种方案都挺好,大同小异。

  1. 参考Lua官网给出的Wiki上的文章Building Lua In Windows For Newbies很容易实现,基本上需要两样工具,一是Lua源码,二是编译工具TDM-GCC。
  2. 参照这里,需要安装MinGW,文中还给出了LuaRocks的安装流程。

方法一

构建Lua

  • 安装GCC编译器
    TDM-GCC的安装参照这里

  • 新建一个名为lua-gcc-Install的文件夹,在里面新建文本文档,命名为buil.cmd,将下面的代码复制到该文件中,注意更改你的编译器路径 和 lua版本。

@echo off
:: ========================
:: file build.cmd
:: ========================
setlocal
:: you may change the following variable's value
:: to suit the downloaded version
set lua_version=5.3.2

set work_dir=%~dp0
:: Removes trailing backslash
:: to enhance readability in the following steps
set work_dir=%work_dir:~0,-1%
set lua_install_dir=%work_dir%\lua
set compiler_bin_dir=E:\devtools\TDM-GCC-64\bin
set lua_build_dir=%work_dir%\lua-%lua_version%
set path=%compiler_bin_dir%;%path%

cd /D %lua_build_dir%
mingw32-make PLAT=mingw

echo.
echo **** COMPILATION TERMINATED ****
echo.
echo **** BUILDING BINARY DISTRIBUTION ****
echo.

:: create a clean "binary" installation
mkdir %lua_install_dir%
mkdir %lua_install_dir%\doc
mkdir %lua_install_dir%\bin
mkdir %lua_install_dir%\include

copy %lua_build_dir%\doc\*.* %lua_install_dir%\doc\*.*
copy %lua_build_dir%\src\*.exe %lua_install_dir%\bin\*.*
copy %lua_build_dir%\src\*.dll %lua_install_dir%\bin\*.*
copy %lua_build_dir%\src\luaconf.h %lua_install_dir%\include\*.*
copy %lua_build_dir%\src\lua.h %lua_install_dir%\include\*.*
copy %lua_build_dir%\src\lualib.h %lua_install_dir%\include\*.*
copy %lua_build_dir%\src\lauxlib.h %lua_install_dir%\include\*.*
copy %lua_build_dir%\src\lua.hpp %lua_install_dir%\include\*.*

echo.
echo **** BINARY DISTRIBUTION BUILT ****
echo.

%lua_install_dir%\bin\lua.exe -e"print [[Hello!]];print[[Simple Lua test successful!!!]]"

echo.

pause
  • 将解压后的lua源码文件放入lua-gcc-install文件夹中,运行build.cmd文件,等待提示完成即可看到lua-gcc-install文件夹下多了一个lua文件夹(bin子文件夹下包含了需要的文件),如下图所示:
    这里写图片描述

安装Lua
将上述构建的文件(bin下的文件)复制到你的安装目录,并添加路径至PATH环境变量即可。
注:由于是用GCC编译生成的,所以在其它木有GCC的平台上是不能运行的。

方法2

参考Installing Lua on a Windows system,包含以下内容:

  1. install a compiler (MinGW (and MSYS))
  2. compile and install Lua
  3. install LuaRocks

install a compiler ([MinGW (and MSYS)]

这里,我用的MinGW中的GCC版本为4.8.1,且安装在“E:\devtools”目录下,所以添加:E:\devtools\MinGw\bin;到系统环境变量PATH。

compile and install Lua

Lua下载Lua源码,我用的Lua5.3.2,解压到任意路径,如:”E:\lua-5.3.2”,然后以管理员身份打开命令提示符(管理员),输入如下指令:

SET PATH=%PATH%;E:\devtools\MinGW\msys\1.0\bin
cd /d E:\lua-5.3.2
make clean
make mingw
make install INSTALL_TOP=E:/devtools/lua/5.3 TO_BIN="lua.exe luac.exe lua53.dll"

输出结果类似这样:

C:\windows\system32>>SET PATH=%PATH%;E:\devtools\MinGW\msys\1.0\bin

C:\windows\system32>cd /d E:\lua-5.3.2

E:\lua-5.3.2>make clean
cd src && make clean
make[1]: Entering directory `/e/lua-5.3.2/src'
rm -f liblua.a lua luac lapi.o lcode.o lctype.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o lmem.o lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o ltm.o lundump.o lvm.o lzio.o lauxlib.o lbaselib.o lbitlib.o lcorolib.o ldblib.o liolib.o lmathlib.o loslib.o lstrlib.o ltablib.o lutf8lib.o loadlib.o linit.o  lua.o luac.o
make[1]: Leaving directory `/e/lua-5.3.2/src'

E:\lua-5.3.2>make mingw
cd src && make mingw
make[1]: Entering directory `/e/lua-5.3.2/src'
make "LUA_A=lua53.dll" "LUA_T=lua.exe" \
        "AR=gcc -std=gnu99 -shared -o" "RANLIB=strip --strip-unneeded" \
        "SYSCFLAGS=-DLUA_BUILD_AS_DLL" "SYSLIBS=" "SYSLDFLAGS=-s" lua.exe
make[2]: Entering directory `/e/lua-5.3.2/src'
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_2 -DLUA_BUILD_AS_DLL    -c -o lua.o lua.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_2 -DLUA_BUILD_AS_DLL    -c -o lapi.o lapi.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_2 -DLUA_BUILD_AS_DLL    -c -o lcode.o lcode.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_2 -DLUA_BUILD_AS_DLL    -c -o lctype.o lctype.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_2 -DLUA_BUILD_AS_DLL    -c -o ldebug.o ldebug.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_2 -DLUA_BUILD_AS_DLL    -c -o ldo.o ldo.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_2 -DLUA_BUILD_AS_DLL    -c -o ldump.o ldump.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_2 -DLUA_BUILD_AS_DLL    -c -o lfunc.o lfunc.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_2 -DLUA_BUILD_AS_DLL    -c -o lgc.o lgc.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_2 -DLUA_BUILD_AS_DLL    -c -o llex.o llex.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_2 -DLUA_BUILD_AS_DLL    -c -o lmem.o lmem.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_2 -DLUA_BUILD_AS_DLL    -c -o lobject.o lobject.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_2 -DLUA_BUILD_AS_DLL    -c -o lopcodes.o lopcodes.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_2 -DLUA_BUILD_AS_DLL    -c -o lparser.o lparser.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_2 -DLUA_BUILD_AS_DLL    -c -o lstate.o lstate.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_2 -DLUA_BUILD_AS_DLL    -c -o lstring.o lstring.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_2 -DLUA_BUILD_AS_DLL    -c -o ltable.o ltable.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_2 -DLUA_BUILD_AS_DLL    -c -o ltm.o ltm.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_2 -DLUA_BUILD_AS_DLL    -c -o lundump.o lundump.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_2 -DLUA_BUILD_AS_DLL    -c -o lvm.o lvm.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_2 -DLUA_BUILD_AS_DLL    -c -o lzio.o lzio.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_2 -DLUA_BUILD_AS_DLL    -c -o lauxlib.o lauxlib.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_2 -DLUA_BUILD_AS_DLL    -c -o lbaselib.o lbaselib.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_2 -DLUA_BUILD_AS_DLL    -c -o lbitlib.o lbitlib.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_2 -DLUA_BUILD_AS_DLL    -c -o lcorolib.o lcorolib.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_2 -DLUA_BUILD_AS_DLL    -c -o ldblib.o ldblib.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_2 -DLUA_BUILD_AS_DLL    -c -o liolib.o liolib.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_2 -DLUA_BUILD_AS_DLL    -c -o lmathlib.o lmathlib.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_2 -DLUA_BUILD_AS_DLL    -c -o loslib.o loslib.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_2 -DLUA_BUILD_AS_DLL    -c -o lstrlib.o lstrlib.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_2 -DLUA_BUILD_AS_DLL    -c -o ltablib.o ltablib.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_2 -DLUA_BUILD_AS_DLL    -c -o lutf8lib.o lutf8lib.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_2 -DLUA_BUILD_AS_DLL    -c -o loadlib.o loadlib.c
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_2 -DLUA_BUILD_AS_DLL    -c -o linit.o linit.c
gcc -std=gnu99 -shared -o lua53.dll lapi.o lcode.o lctype.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o lmem.o lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o ltm.o lundump.o lvm.o lzio.o lauxlib.o lbaselib.o lbitlib.o lcorolib.o ldblib.o liolib.o lmathlib.o loslib.o lstrlib.o ltablib.o lutf8lib.o loadlib.o linit.o
strip --strip-unneeded lua53.dll
gcc -std=gnu99 -o lua.exe -s  lua.o lua53.dll -lm
make[2]: Leaving directory `/e/lua-5.3.2/src'
make "LUAC_T=luac.exe" luac.exe
make[2]: Entering directory `/e/lua-5.3.2/src'
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_2     -c -o luac.o luac.c
ar rcu liblua.a lapi.o lcode.o lctype.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o lmem.o lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o ltm.o lundump.o lvm.o lzio.o lauxlib.o lbaselib.o lbitlib.o lcorolib.o ldblib.o liolib.o lmathlib.o loslib.o lstrlib.o ltablib.o lutf8lib.o loadlib.o linit.o
ranlib liblua.a
gcc -std=gnu99 -o luac.exe   luac.o liblua.a -lm
make[2]: Leaving directory `/e/lua-5.3.2/src'
make[1]: Leaving directory `/e/lua-5.3.2/src'

E:\lua-5.3.2>make install INSTALL_TOP=E:/devtools/lua/5.3 TO_BIN="lua.exe luac.exe lua53.dll"
cd src && mkdir -p E:/devtools/lua/5.3/bin E:/devtools/lua/5.3/include E:/devtools/lua/5.3/lib E:/devtools/lua/5.3/man/man1 E:/devtools/lua/5.3/share/lua/5.3 E:/devtools/lua/5.3/lib/lua/5.3
cd src && install -p -m 0755 lua.exe luac.exe lua53.dll E:/devtools/lua/5.3/bin
cd src && install -p -m 0644 lua.h luaconf.h lualib.h lauxlib.h lua.hpp E:/devtools/lua/5.3/include
cd src && install -p -m 0644 liblua.a E:/devtools/lua/5.3/lib
cd doc && install -p -m 0644 lua.1 luac.1 E:/devtools/lua/5.3/man/man1

E:\lua-5.3.2>

最后一步是添加Lua安装路径E:\devtools\lua\5.3\bin到系统环境变量PATH。

在cmd终端输入:lua即可进入Lua解释器交互界面,也可以输入lua -e "print('hello world')"来测试安装是否正确(打印出hello world)。

install LuaRocks

下载Windows版的LuaRocks,解压到E盘,然后输入如下命令安装,其中,/P E:\devtools\LuaRocks指定安装目录,可以使用install /?查看更多选项。

cd luarocks-2.3.0-win32
install /MW /F /LV 5.3 /P E:\devtools\LuaRocks

:执行完毕后,末尾打印如下类似信息,告诉你如何添加环境变量:

============================
== LuaRocks is installed! ==
============================


You may want to add the following elements to your paths;
Lua interpreter;
  PATH     :   E:\devtools\lua\5.3\bin\
  PATHEXT  :   .LUA
LuaRocks;
  PATH     :   E:\devtools\LuaRocks
  LUA_PATH :   E:\devtools\LuaRocks\lua\?.lua;E:\devtools\LuaRocks\lua\?\init.lua
Local user rocktree (Note: %APPDATA% is user dependent);
  PATH     :   %APPDATA%\LuaRocks\bin
  LUA_PATH :   %APPDATA%\LuaRocks\share\lua\5.3\?.lua;%APPDATA%\LuaRocks\share\lua\5.3\?\init.lua
  LUA_CPATH:   %APPDATA%\LuaRocks\lib\lua\5.3\?.dll
System rocktree
  PATH     :   e:\devtools\lua\5.3\\bin
  LUA_PATH :   e:\devtools\lua\5.3\\share\lua\5.3\?.lua;e:\devtools\lua\5.3\\share\lua\5.3\?\init.lua
  LUA_CPATH:   e:\devtools\lua\5.3\\lib\lua\5.3\?.dll

Note that the %APPDATA% element in the paths above is user specific and it MUST be replaced by its actual value.
For the current user that value is: C:\Users\liu\AppData\Roaming.

根据上述,添加必要的环境变量,由于PATH已经存在,所以只需要LUA_PATHLUA_CPATH,文Installing Lua on a Windows system中说,对于Lua5.3,添加LUA_PATH_5_3LUA_CPATH_5_3,我试了一下,两个都对,如果你安装了不同版本的Lua,应该用后者指示不同版本。

为测试LuaRocks安装正确,cmd命令行输入luarocks help会打印很多帮助信息。

比如可以通过luarocks install pakage来安装包,通过luarocks remove pakage来卸载包

举例:安装luafilesystem

C:\windows\system32>luarocks install luafilesystem
Installing https://luarocks.org/luafilesystem-1.6.3-2.src.rock...
Using https://luarocks.org/luafilesystem-1.6.3-2.src.rock... switching to 'build' mode
mingw32-gcc -O2 -c -o src/lfs.o -IE:/devtools/lua/5.3/include/ src/lfs.c
In file included from src/lfs.c:67:0:
src/lfs.h:21:0: warning: "fileno" redefined [enabled by default]
 #define fileno(f) (_fileno(f))
 ^
In file included from src/lfs.c:38:0:
e:\devtools\mingw\include\stdio.h:595:0: note: this is the location of the previous definition
 #define fileno(__F) ((__F)->_file)
 ^
mingw32-gcc -shared -o lfs.dll src/lfs.o E:/devtools/lua/5.3/bin/lua53.dll -lm
Updating manifest for e:\devtools\lua\5.3\/lib/luarocks/rocks
luafilesystem 1.6.3-2 is now built and installed in e:\devtools\lua\5.3\ (license: MIT/X11)

语法

多重赋值

在Lua中,多重赋值是合法的,如a,b,c = 1,2,3,则相当于a=1; b=2; c=3。参考Lua 5.3 Reference Manual §3.3.3 – Assignment,可以看到赋值规则是这样的:
[Lua5.3][Lua53refman]

Before the assignment, the list of values is adjusted to the length of the list of variables. If there are more values than needed, the excess values are thrown away. If there are fewer values than needed, the list is extended with as many nil’s as needed. If the list of expressions ends with a function call, then all values returned by that call enter the list of values, before the adjustment (except when the call is enclosed in parentheses; see §3.4).
在作赋值操作之前,那值列表会被 调整 为左边变量列表的个数。如果值比需要的更多的话,多余的值就被扔掉。 如果值的数量不够需求,将会按所需扩展若干个 nil。如果表达式列表以一个函数调用结束,这个函数所返回的所有值都会在调整操作之前被置入值列表中(除非这个函数调用被用括号括了起来;参见 §3.4)。

The assignment statement first evaluates all its expressions and only then the assignments are performed.
赋值语句首先让所有的表达式完成运算,之后再做赋值操作。

看下面一段代码及其对应输出,函数maxmin有两个返回值,依次输出两个输入参数的最大和最小。

function maxmin( a, b )
    if a < b then
        return b, a
    else
        return a,b
    end
end

a, b, c, d = maxmin(2,3), 1, 4
print(a,b,c,d)                 -- <---> 3   1   4   nil

a, b, c, d = 1, maxmin(2,3), 4
print(a,b,c,d)                 -- <---> 1   3   4   nil

a, b, c, d = 1, 4, maxmin(2,3)
print(a,b,c,d)                 -- <---> 1   4   3   2

a, b, c, d = 1, 4, (maxmin(2,3))
print(a,b,c,d)                 -- <---> 1   4   3   nil

i = 3; a = {}
i, a[i] = i+1, 20
print(i, a[3], a[4])           -- <---> 4   20  nil

-- swap value
x = 1; y = 2; z = 3
x,y,z = y,z,x
print(x,y,z)                   -- <---> 2   3   1

由上面的规则可知:1. 只有当表达式列表以一个函数调用结束,并且函数调用没有被用括号()扩起来,这个函数所返回的所有值才会在调整操作之前都被置入值列表中,所以只有a, b, c, d = 1, 4, maxmin(2,3)对应的右端值列表中有4个值;2. 赋值语句首先让所有的表达式完成运算,之后再做赋值操作,所以i, a[i] = i+1, 20,只改变了a[3]的值。

协同

  • 线程和协同主要区别:线程同时运行多个线程,协同在同一时刻只有一个协同程序运行,且只有在运行的协同程序明确要求挂起才挂起;
  • 给 yield 的参数 会传给resume,主函数返回值也会传给resume,传给resume的参数也会传给yield;
  • yield 是挂起程序,resume时,yield接受resume传来的新的参数,从挂起处开始执行;
co = coroutine.create(function ( )
    print('suspended follows:')
    print("co", coroutine.yield())
    -- body
end)
print(coroutine.resume(co))         --> suspended follows -->true
print(coroutine.status(co))         --> suspended
print(coroutine.resume(co, 4, 5))   -- co   4   5  -->true
print(coroutine.status(co))         --> dead
print(coroutine.resume(co, 4, 5))   --> false   cannot resume dead coroutine


print('------------')
co = coroutine.create(function()
    return 6, 7
end)
print(coroutine.resume(co))         --> true    6   7

GUI开发

可以使用 wxLua 进行 GUI 开发,参考 Build using GCC in Linux 在Linux上安装,Windows上直接下载二进制包安装即可。


2012-10-16 14:59:45 goodai007 阅读数 69527

time和date两个函数在Lua中实现所有的时钟查询功能。函数time在没有参数时返回当前时钟的数值。(在许多系统中该数值是当前距离某个特定时间的秒数。)当为函数调用附加一个特殊的时间表时,该函数就是返回距该表描述的时间的数值。这样的时间表有如下的区间:

year

a full year

month

01-12

day

01-31

hour

01-31

min

00-59

sec

00-59

isdst

a boolean, true if daylight saving

前三项是必需的,如果未定义后几项,默认时间为正午(12:00:00)。如果是在里约热内卢(格林威治向西三个时区)的一台Unix计算机上(相对时间为1970年1月1日,00:00:00)执行如下代码,其结果将如下。

-- obs: 10800 = 3*60*60 (3 hours)

print(os.time{year=1970, month=1, day=1, hour=0})

    --> 10800

print(os.time{year=1970, month=1, day=1, hour=0, sec=1})

    --> 10801

print(os.time{year=1970, month=1, day=1})

    --> 54000   (obs: 54000 = 10800 + 12*60*60)


os.time()                <== 返回当前系统的日历时间
os.date()                <== 返回本地化的时间字符串,这里是"11/28/08 17:23:37"
os.date("%x", os.time()) <== 返回自定义格式化时间字符串(完整的格式化参数),这里是"11/28/08"
os.clock()               <== 返回执行该程序CPU花去的时钟秒数,这里是1156.726


函数data,不管它的名字是什么,其实是time函数的一种“反函数”。它将一个表示日期和时间的数值,转换成更高级的表现形式。其第一个参数是一个格式化字符串,描述了要返回的时间形式。第二个参数就是时间的数字表示,默认为当前的时间。使用格式字符 "*t",创建一个时间表。例如下面这段代码:

temp = os.date("*t", 906000490)

则会产生表

{year = 1998, month = 9, day = 16, yday = 259, wday = 4,

 hour = 23, min = 48, sec = 10, isdst = false}

不难发现该表中除了使用到了在上述时间表中的区域以外,这个表还提供了星期(wday,星期天为1)和一年中的第几天(yday,一月一日为1)除了使用 "*t" 格式字符串外,如果使用带标记(见下表)的特殊字符串,os.data函数会将相应的标记位以时间信息进行填充,得到一个包含时间的字符串。(这些特殊标记都是以 "%" 和一个字母的形式出现)如下:

print(os.date("today is %A, in %B"))

    --> today is Tuesday, in May

print(os.date("%x", 906000490))

    --> 09/16/1998

这些时间输出的字符串表示是经过本地化的。所以如果是在巴西(葡萄牙语系),"%B" 得到的就是 "setembro"(译者按:大概是葡萄牙语九月?),"%x" 得到的就是 "16/09/98"(月日次序不同)。标记的意义和显示实例总结如下表。实例的时间是在1998年九月16日,星期三,23:48:10。返回值为数字形式的还列出了它们的范围。(都是按照英语系的显示描述的,也比较简单,就不烦了)

%a

abbreviated weekday name (e.g., Wed)

%A

full weekday name (e.g., Wednesday)

%b

abbreviated month name (e.g., Sep)

%B

full month name (e.g., September)

%c

date and time (e.g., 09/16/98 23:48:10)

%d

day of the month (16) [01-31]

%H

hour, using a 24-hour clock (23) [00-23]

%I

hour, using a 12-hour clock (11) [01-12]

%M

minute (48) [00-59]

%m

month (09) [01-12]

%p

either "am" or "pm" (pm)

%S

second (10) [00-61]

%w

weekday (3) [0-6 = Sunday-Saturday]

%x

date (e.g., 09/16/98)

%X

time (e.g., 23:48:10)

%Y

full year (1998)

%y

two-digit year (98) [00-99]

%%

the character '%'

事实上如果不使用任何参数就调用date,就是以%c的形式输出。这样就是得到经过格式化的完整时间信息。还要注意%x、%X和%c由所在地区和计算机系统的改变会发生变化。如果该字符串要确定下来(例如确定为mm/dd/yyyy),可以使用明确的字符串格式方式(例如"%m/%d/%Y")。

函数os.clock返回执行该程序CPU花去的时钟秒数。该函数常用来测试一段代码。

local x = os.clock()

local s = 0

for i=1,100000 do s = s + i end

print(string.format("elapsed time: %.2f\n", os.clock() - x))

2019-10-15 17:54:12 weixin_43250979 阅读数 11

Lua time [os.time()] [os.date()]


核心方法


os.time()

os.time([table]): 按给定的参数(table格式)的内容返回一个时间值(数字)

  • 不传参的话返回当前时间转化成秒数的结果。(从格林尼治时间1970.01.01 00:00:00开始计时)
    print(os.time())
    ==========
    result:
    1561033140
    
  • 其中参数table中可以包含的字段有:year, month, day, hour, min, sec, isdst(夏令时),其他字段将会被忽略。可以使用该方法可以指定时间。
    • print(os.time({year =2019, month = 06, day = 20, hour = 20, min = 19, sec = 00}))
      ==========
      result:
      1561033140
      
    • print(os.time({year =1919, month = 06, day = 20, hour = 20, min = 19, sec = 00}))
      ==========
      result:
      nil
      
    • 注意:如果填了参数,year, month, day 则为必填参数,少填任意一个都会报错

os.date()

  • os.date ([format [, time]]). 返回format格式化日期、时间的字串或表。

  • 如果format!开头,则格式化使用的时间为格林尼治时间。

  • 如果format不是*t,os.date会将日期格式化为一个字符串。

  • 如果format是*t,将返一个带year(4位)(%Y),month(1-12), day (1–31), hour (0-23), min (0-59),sec (0-61),wday (星期几, 星期天为1), yday (年内天数)和isdst (是否为日光节约时间true/false)的带键名的表。

  • 举例:

    • print(os.date("%Y%m%d%H%M%S", os.time()))
      print(os.date("!%Y%m%d%H%M%S", os.time()))
      ==========
      result: 
      20191015170052
      20191015090052
      
    • print(os.date("%Y-%m-%d-%H-%M-%S", os.time()))
      ==========
      result: 
      2019-10-15-17-00-52
      
    • print(os.date("%Y-%m-%d %H:%M:%S", os.time()))
      ==========
      result: 
      2019-10-15 17:00:52
      
    • local data = os.date('*t', os.time())
      
      for k, v in pairs(data) do
      	print(k, v)
      end
      ==========
      result:
      wday		3
      yday		288
      sec			6
      min			53
      day			15
      month		10
      isdst		false
      year		2019
      hour		16
      
  • os.date()格式符:

    式符 含义 示例 [] 表示范围
    %a 一星期中天数的简写 (Fri)
    %A 一星期中天数的全称 (Wednesday)
    %b 月份的简写 (Sep)
    %B 月份的全称 (May)
    %c 日期和时间 (09/16/98 23:48:10)
    %d 一个月中的第几天 (28)[0 - 31]
    %H 24小时制中的小时数 (18)[00 - 23]
    %I 12小时制中的小时数 (10)[01 - 12]
    %j 一年中的第几天 (209)[01 - 366]
    %M 分钟数 (48)[00 - 59]
    %m 月份数 (09)[01 - 12]
    %P 上午或下午 (pm)[am - pm]
    %S 一分钟之内秒数 (10)[00 - 59]
    %w 一星期中的第几天 (3)[0 - 6 = 星期天 - 星期六]
    %W 一年中的第几个星期 (2)0 - 52
    %x 日期 (09/16/98)
    %X 时间 (23:48:10)
    %y 两位数的年份 (16)[00 - 99]
    %Y 完整的年份 (2016)
    %% 字符串’%’ (%)

拓展用法

  • 计算时区
    • print(os.difftime(os.time(), os.time(os.date('!*t', os.time()))) / 3600)
      =======
      result:
      8.0
      
  • 获取指定月份总共有多少天
    • function GetTotalDaysByYearAndMonth(_year, _month)
          local _date = {}
          _date.year = _year
          _date.month = _month + 1
          _date.day = 0
          local _days= os.date("%d",os.time(_date))			--下个月的第0天即当月的最后一天
          return _days
      end
      
      print(GetTotalDaysByYearAndMonth(2000, 2))
      
2014-01-17 01:04:16 Liar0606 阅读数 2137

解释器是一个小型的程序。

解释器程序的用法:

lua的解析器如果加载了一个文件,文件第一行为#开头,那么第一行会被忽略掉。这个特性保证了Lua在Unix系统下的正常运行,例如

#!/usr/local/bin/lua       or           #!/usr/bin/env lua

Lua [选项参数] [脚本[参数]]

如果不使用任何参数来启动解释器时,就会直接进入交互模式。

所选参数”-e” 可以直接在命令行输入代码,如:

Lua –e “print(math.sin(12))”   -->0.536…

选项参数”-l”用于加载库文件。而是用”-i”如先前说的,表示在运行完成其他命令行参数后进入交互模式。

lua –i –l a –e “x=10”        

顺序:先加载库文件a,然后执行语句”x=10”,最后进入交互模式。

利用全局变量_PROMPT来改变交互模式的提示符,假如之前是:

lua%

执行lua -i -e "_PROMPT='lua>'"

提示符将会变为:lua>

在交互模式中,打印任何表达式的值,可以用等号开头,并跟随一个表达式。例如:

>=math.sin(3) -->-.14112..

>a=30

>=a -->30

2019-12-10 20:07:54 qq_41453285 阅读数 33
  • 除了EVAL命令和EVALSHA命令之外,Redis中与Lua脚本有关的命令还有四个,它们分别是:SCRIPT FLUSH命令、SCRIPT EXISTS命令、SCRIPT LOAD命令、以及SCRIPT KILL命 令

一、SCRIPT FLUSH

  • SCRIPT FLUSH命令用于:
    • 清除服务器中所有和Lua脚本有关的信息
    • 这个命令会释放并重建lua_scripts字典
    • 关闭现有的Lua环境并重新创建一个新的Lua环境
  • 以下为SCRIPT FLUSH命令的实现伪代码:
def SCRIPT_FLUSH():
    # 释放脚本字典
    dictRelease(server.lua_scripts)
    # 重建脚本字典
    server.lua_scripts = dictCreate(...)
    # 关闭Lua 环境
    lua_close(server.lua)
    # 初始化一个新的Lua 环境
    server.lua = init_lua_env()

二、SCRIPT EXISTS

  • SCRIPT EXISTS命令根据输入的SHA1校验和,检查校验和对应的脚本是否存在于服务器中
  • SCRIPT EXISTS命令是通过检查给定的校验和是否存在于lua_scripts字典来实现的
  • 以下是该命令的实现伪代码:
def SCRIPT_EXISTS(*sha1_list):
    # 结果列表
    result_list = []
    #遍历输入的所有SHA1 校验和
    for sha1 in sha1_list:
        # 检查校验和是否为lua_scripts 字典的键
        # 如果是的话,那么表示校验和对应的脚本存在
        # 否则的话,脚本就不存在
        if sha1 in server.lua_scripts:
            # 存在用1 表示
            result_list.append(1)
        else:
            # 不存在用0 表示
            result_list.append(0)
    # 向客户端返回结果列表
    send_list_reply(result_list)

演示案例

  •  举个例子,对于下图所示的lua_scripts字典来说,我们可以进行以下测试:

  • 注意:SCRIPT EXISTS命令允许一次传入多个SHA1校验和,不过因为SHA1校验和太长,所以示例里分开多次来进行测试
  • 实现SCRIPT EXISTS实际上并不需要lua_scripts字典的值。如果lua_scripts字典只用于实现SCRIPT EXISTS命令的话,那么字典只需要保存Lua脚本的SHA1校验和就可以了,并不需要保存Lua脚本本身。lua_scripts字典既保存脚本的SHA1校验和,又保存脚本本身的原因是为了实现脚本复制功能(详情请见下一篇文章的脚本复制功能实现)

三、SCRIPT LOAD

  • SCRIPT LOAD命令只加载/保存脚本,但是不执行脚本
  • 命令首先在Lua环境中为脚本创建相对应的函数,然后再将脚本保存到lua_scripts字典里面

演示案例

  • 举个例子,如果我们执行以下命令:

  • 那么服务器将在Lua环境中创建以下函数:

  • 并将键为"2f31ba2bb6d6a0f42cc159d2e2dad55440778de3",值为"return'hi'"的键值对添加 到服务器的lua_scripts字典里面,如下图所示:

  • 完成了这些步骤之后,客户端就可以使用EVALSHA命令来执行前面被SCRIPT LOAD命令载入的脚本了:

四、SCRIPT KILL

  • 如果服务器设置了lua-time-limit配置选项,那么在每次执行Lua脚本之前,服务器都会在Lua环境里面设置一个超时处理钩子(hook)
  • 超时处理钩子在脚本运行期间,会定期检查脚本已经运行了多长时间,一旦钩子发现脚本的运行时间已经超过了lua-time-limit选项设置的时长,钩子将定期在脚本运行的间隙中, 查看是否有SCRIPT KILL命令或者SHUTDOWN命令到达服务器
  • 下图展示了带有超时处理钩子的脚本的运行过程:
    • 如果超时运行的脚本未执行过任何写入操作,那么客户端可以通过SCRIPT KILL命令来指示服务器停止执行这个脚本,并向执行该脚本的客户端发送一个错误回复。处理完SCRIPT KILL命令之后,服务器可以继续运行
    • 如果脚本已经执行过写入操作,那么客户端只能用SHUTDOWN nosave命令来停止服务器,从而防止不合法的数据被写入数据库中

Lua

阅读数 1281

Lua的time相关函数

阅读数 615

Lua之Date和Time

阅读数 153

没有更多推荐了,返回首页