第 21 章 操作系统库
操作系统库包含了文件管理,系统时钟等等与操作系统相关信息。这些函数定义在表(table)os 中。定义该库时考虑到 Lua 的可移植性,因为 Lua是以 ANSI C 写成的, 所以只能使用 ANSI 定义的一些标准函数。许多的系统属性并不包含在 ANSI 定义中, 例如目录管理,套接字等等。所以在系统库里并没有提供这些功能。另外有一些没有包含在主体发行版中的 Lua库提供了操作系统扩展属性的访问。例如 posix 库,提供了对POSIX 1 标准的完全支持;在比如 luasocket 库,提供了网络支持。
在文件管理方面操作系统库就提供了 os.rename 函数(修改文件名)和 os.remove 函 数(删除文件)。
21.1 Date 和 Time
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 |
-- obs: 10800= 3*60*60 (3hours) 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)
函数 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 isTuesday, 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))
21.2 其它的系统调用
函数 os.exit 终止一个程序的执行。函数 os.getenv 得到"环境变量"的值。以"变量 名"作为参数,返回该变量值的字符串:
print(os.getenv("HOME")) --> /home/lua
如果没有该环境变量则返回 nil。函数 os.execute 执行一个系统命令(和 C 中的 system 函数等价 )。该函数获 取一个命令 字符串,返 回一个错误 代码。例如 在 Unix 和 DOS-Windows 系统里都可以执行如下代码创建一个新目录:
function createDir (dirname) os.execute("mkdir " .. dirname) end
os.execute 函数较为强大,同时也更加倚赖于计算机系统。函数 os.setlocale设定 Lua 程序所使用的区域(locale)。区域定义的变化对于文化和语言是相当敏感的。setlocale 有两个字符串参数:区域名和特性(category,用来表示区域的各项特性)。在区域中包 含六项特性:"collate"(排序)控制字符的排列顺序;"ctype"controls the types of individualcharacters (e.g., what is a letter) and the conversion between lower and upper cases; "monetary"(货币)对 Lua程序没有影响;"numeric"(数字)控制数字的格式;"time"控制时间的格式(也就是 os.date 函数);和"all"包含以上所以特性。函数默认的特性 就是"all",所以如果你只包含地域名就调用函数setlocale 那么所有的特性都会被改变为 新的区域特性。如果运行成功函数返回地域名,否则返回 nil(通常因为系统不支持给定 的区域)。
print(os.setlocale("ISO-8859-1", "collate")) --> ISO-8859-1
关于"numeric"特性有一点难处理的地方。尽管葡萄牙语和其它的一些拉丁文语言使用逗号代替点号来表示十进制数,但是区域设置并不会改变Lua划分数字的方式。(除了其它一些原因之外,由于print(3,4)还有其它的函数意义。)因此设置之后得到的系统也许既不能识别带逗号的数值,又不能理解带点号的数值:
-- 设置区域为葡萄牙语系巴西 print(os.setlocale('pt_BR')) --> pt_BR print(3,4) --> 3 4 print(3.4) --> stdin:1: malformed numbernear `3.4'
The category "numeric" is a little tricky. Although Portuguese and other Latin languages usea comma instead of a point to represent decimal numbers, the locale does not change thewaythat Lua parses numbers (among other reasonsbecause expressions like print(3,4) alreadyhave a meaning in Lua). Therefore,you may end with a system that cannot recognize numbers withcommas,but cannot understand numberswithpointseither:
<pre name="code" class="csharp">-- set locale forPortuguese-Brazil print(os.setlocale('pt_BR')) --> pt_BR print(3,4) --> 3 4 print(3.4) --> stdin:1: malformed numbernear '3.4'