4. 标准库

2018-02-24 16:10 更新

String

string.byte
string.char
string.dump
string.find
string.format
string.gmatch
string.gsub
string.len
string.lower
string.match
string.rep
string.reverse
string.sub
string.upper

在string库中功能最强大的函数是:string.find(字符串查找),string.gsub(全局字符串替换),and string.gfind(全局字符串查找)。这些函数都是基于模式匹配的。

与其他脚本语言不同的是,Lua并不使用POSIX规范的正则表达式(也写作regexp)来进行模式匹配。主要的原因出于程序大小方面的考虑:实现一个典型的符合POSIX标准的regexp大概需要4000行代码,这比整个Lua标准库加在一起都大。权衡之下,Lua中的模式匹配的实现只用了500行代码,当然这意味着不可能实现POSIX所规范的所有更能。然而,Lua中的模式匹配功能是很强大的,并且包含了一些使用标准POSIX模式匹配不容易实现的功能。

(1) pattern 模式

下面的表列出了Lua支持的所有字符类:

.      任意字符
%a     字母
%c     控制字符
%d     数字
%l     小写字母
%p     标点字符
%s     空白符
%u     大写字母
%w     字母和数字
%x     十六进制数字
%z     代表0的字符

可以使用修饰符来修饰模式增强模式的表达能力,Lua中的模式修饰符有四个:

+      匹配前一字符1次或多次
*      匹配前一字符0次或多次
-      匹配前一字符0次或多次
?      匹配前一字符0次或1次

'%b' 用来匹配对称的字符。常写为 '%bxy' ,x和y是任意两个不同的字符;x作为匹配的开始,y作为匹配的结束。比如,'%b()' 匹配以 '(' 开始,以 ')' 结束的字符串:

print(string.gsub("a (enclosed (in) parentheses) line", "%b()", "")) --> a  line

常用的这种模式有:'%b()' ,'%b[]','%b%{%}' 和 '%b<>'。你也可以使用任何字符作为分隔符。

(2) capture 捕获

Capture是这样一种机制:可以使用模式串的一部分匹配目标串的一部分。将你想捕获的模式用圆括号括起来,就指定了一个capture。

pair = "name = Anna"
_, _, key, value = string.find(pair, "(%a+)%s*=%s*(%a+)")
print(key, value)    --> name   Anna

(3) string.find 字符串查找

string.find 的基本应用就是用来在目标串(subject string)内搜索匹配指定的模式的串,函数返回两个值:匹配串开始索引和结束索引。

s = "hello world"
i, j = string.find(s, "hello")
print(i, j)                        --> 1    5
print(string.sub(s, i, j))         --> hello
print(string.find(s, "world"))     --> 7    11
i, j = string.find(s, "l")
print(i, j)                        --> 3    3
print(string.find(s, "lll"))       --> nil

string.find函数第三个参数是可选的:标示目标串中搜索的起始位置。

在string.find使用captures的时候,函数会返回捕获的值作为额外的结果:

pair = "name = Anna"
_, _, key, value = string.find(pair, "(%a+)%s*=%s*(%a+)")
print(key, value)    --> name   Anna

看个例子,假定你想查找一个字符串中单引号或者双引号引起来的子串,你可能使用模式 '["'].-["']',但是这个模式对处理类似字符串 "it's all right" 会出问题。为了解决这个问题,可以使用向前引用,使用捕获的第一个引号来表示第二个引号:

s = [[then he said: "it's all right"!]]
a, b, c, quotedPart = string.find(s, "(["'])(.-)%1")
print(quotedPart)    --> it's all right
print(c)             --> "

(4) string.gmatch 全局字符串查找

string.gfind 函数比较适合用于范性 for 循环。他可以遍历一个字符串内所有匹配模式的子串。

words = {}
for w in string.gmatch("nick takes a stroll", "%a+") do
    table.insert(words, w)
end

URL解码

function unescape(s)
    s = string.gsub(s, "+", " ")
    s = string.gsub(s, "%%(%x%x)", function(h)
        return string.char(tonumber(h, 16))
    end)
    return s
end

print(unescape("a%2Bb+%3D+c")) -- a+b = c

对于name=value对,我们使用gfind解码,因为names和values都不能包含 '&' 和 '='我们可以用模式 '[^&=]+' 匹配他们:

cgi = {}
function decode (s)
    for name, value in string.gmatch(s, "([^&=]+)=([^&=]+)") do
       name = unescape(name)
       value = unescape(value)
       cgi[name] = value
    end
end

URL编码

这个函数将所有的特殊字符转换成 '%' 后跟字符对应的ASCII码转换成两位的16进制数字(不足两位,前面补0),然后将空白转换为 '+':

function escape(s)
    s = string.gsub(s, "([&=+%c])", function(c)
        return string.format("%%%02X", string.byte(c))
    end)
    s = string.gsub(s, " ", "+")
    return s
end

function encode(t)
    local s = ""
    for k, v in pairs(t) do
        s = s .. "&" .. escape(k) .. "=" .. escape(v)
    end
    return string.sub(s, 2) -- remove first '&'
end
t = {name = "al", query = "a+b = c", q = "yes or no"}

print(encode(t)) --> q=yes+or+no&query=a%2Bb+%3D+c&name=al

(5) string.gsub 全局字符串替换

string.gsub 函数有三个参数:目标串,模式串,替换串,第四个参数是可选的,用来限制替换的数量。

print(string.gsub("nck eats fish", "fish", "chips")) --> nick eats chips 1

string.gsub 的第二个返回值表示他进行替换操作的次数:

print(string.gsub("fish eats fish", "fish", "chips")) --> chips eats chips 2

使用模式:

print(string.gsub("nick eats fish", "[AEIOUaeiou]", ".")) --> n.ck ..ts f.sh 4

使用捕获:

print(string.gsub("nick eats fish", "([AEIOUaeiou])", "(%1)")) --> n(i)ck (e)(a)ts f(i)sh 4

使用替换函数:

function f(s)
    print("found " .. s)
end

string.gsub("Nick is taking a walk today", "%a+", f)

输出:
found Nick
found is
found taking
found a
found walk
found today

(6) string.sub, string.byte, string.format

s = "[in brackets]"
print(string.sub(s, 2, -2))     --> in brackets

string.char 函数和 string.byte 函数用来将字符在字符和数字之间转换,string.char 获取0个或多个整数,将每一个数字转换成字符,然后返回一个所有这些字符连接起来的字符串。string.byte(s, i) 将字符串s的第i个字符的转换成整数。

print(string.char(97))                    --> a
i = 99; print(string.char(i, i+1, i+2))   --> cde
print(string.byte("abc"))                 --> 97
print(string.byte("abc", 2))              --> 98
print(string.byte("abc", -1))             --> 99

string.format 和 C 语言的 printf 函数几乎一模一样,你完全可以照 C 语言的 printf 来使用这个函数,第一个参数为格式化串:由指示符和控制格式的字符组成。指示符后的控制格式的字符可以为:十进制'd';十六进制'x';八进制'o';浮点数'f';字符串's'。

print(string.format("pi = %.4f", PI)) --> pi = 3.1416
d = 5; m = 11; y = 1990
print(string.format("%02d/%02d/%04d", d, m, y)) --> 05/11/1990
tag, title = "h1", "a title"
print(string.format("<%s>%s</%s>", tag, title, tag)) --> <h1>a title</h1>

Table

table.concat
table.insert
table.maxn
table.remove
table.sort

(1) table.getn

print(table.getn{10,2,4})          --> 3
print(table.getn{10,2,nil})        --> 2
print(table.getn{10,2,nil; n=3})   --> 3
print(table.getn{n=1000})          --> 1000

a = {}
print(table.getn(a))               --> 0
table.setn(a, 10000)
print(table.getn(a))               --> 10000

a = {n=10}
print(table.getn(a))               --> 10
table.setn(a, 10000)
print(table.getn(a))               --> 10000

(2) table.insert, table.remove

table.isnert(table, value, position)
table.remove(table, position)

table库提供了从一个list的任意位置插入和删除元素的函数。table.insert函数在array指定位置插入一个元素,并将后面所有其他的元素后移。

a = {}
for line in io.lines() do
    table.insert(a, line)
end
print(table.getn(a))        --> (number of lines read)

table.remove 函数删除数组中指定位置的元素,并返回这个元素,所有后面的元素前移,并且数组的大小改变。不带位置参数调用的时候,他删除array的最后一个元素。

(3) table.sort

table.sort 有两个参数,存放元素的array和排序函数,排序函数有两个参数并且如果在array中排序后第一个参数在第二个参数前面,排序函数必须返回true。如果未提供排序函数,sort使用默认的小于操作符进行比较。

lines = {
    luaH_set = 10,
    luaH_get = 24,
    luaH_present = 48,
}

function pairsByKeys (t, f)
    local a = {}
    for n in pairs(t) do table.insert(a, n) end
    table.sort(a, f)
    local i = 0                 -- iterator variable
    local iter = function ()    -- iterator function
       i = i + 1
       if a[i] == nil then return nil
       else return a[i], t[a[i]]
       end
    end
    return iter
end

for name, line in pairsByKeys(lines) do
    print(name, line)
end

打印结果:

luaH_get          24
luaH_present      48
luaH_set          10

Coroutine

coroutine.create
coroutine.resume
coroutine.running
coroutine.status
coroutine.wrap
coroutine.yield

Math

math.abs
math.acos
math.asin
math.atan
math.atan2
math.ceil
math.cos
math.cosh
math.deg
math.exp
math.floor
math.fmod
math.frexp
math.huge
math.ldexp
math.log
math.log10
math.max
math.min
math.modf
math.pi
math.pow
math.rad
math.random
math.randomseed
math.sin
math.sinh
math.sqrt
math.tan
math.tanh

IO

io.close
io.flush
io.input
io.lines
io.open
io.output
io.popen
io.read
io.stderr
io.stdin
io.stdout
io.tmpfile
io.type
io.write

OS

os.clock
os.date
os.difftime
os.execute
os.exit
os.getenv
os.remove
os.rename
os.setlocale
os.time
os.tmpname

File

file:close
file:flush
file:lines
file:read
file:seek
file:setvbuf
file:write

Debug

debug.debug
debug.getfenv
debug.gethook
debug.getinfo
debug.getlocal
debug.getmetatable
debug.getregistry
debug.getupvalue
debug.setfenv
debug.sethook
debug.setlocal
debug.setmetatable
debug.setupvalue
debug.traceback
以上内容是否对您有帮助:
在线笔记
App下载
App下载

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号