快速掌握Lua 5.3 —— 字符串库
Posted VermillionTear
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了快速掌握Lua 5.3 —— 字符串库相关的知识,希望对你有一定的参考价值。
Q:模式匹配字符串的相关函数?
A:
--[[ string.find(s, pattern [, init [, plain]])
在字符串"s"中查找第一个与匹配模式"pattern"相匹配的子串,
函数返回子串的开始位置和终止位置。如果未找到返回"nil"。
如果在"pattern"中定义了捕获,捕获物也会在之后依次返回。
"init"可指定从字符串"s"的什么位置开始查找,默认为1。
"plain"指定是否以模式匹配的形式查找子串,如果"plain"为0,
那么将根据"pattern"的字面意思查找子串,默认为非0值。]]
s = "Hello World! 123 %a+"
print(string.find(s, "l")) --> 3 3
print(string.find(s, "l", 6)) --> 10 10
print(string.find(s, "lll", 6)) --> nil
print(string.find(s, "%a+", 6)) --> 7 11
print(string.find(s, "%a+", 6, 0)) --> 18 20
-- 通过使用第三个参数可以实现查找字符串中所有匹配"pattern"的子串。
local b = 0
local e = 0
while true do
-- 从匹配位置的下一个位置开始继续查找。
b, e = string.find(s, "%a+", e + 1)
if b == nil then break end
io.write(string.format("%s, ", string.sub(s, b, e)))
--> Hello, World, a,
end
print()
--[[ string.gsub(s, pattern, repl [, n])
将字符串"s"中前"n"个与匹配模式"pattern"相匹配的子串替换为"repl",
"n"如果不指定,默认替换所有的匹配。
函数返回被替换后的字符串,以及替换的次数。
1、如果"repl"是一个字符串(其中可以使用捕获物),那么把这个字符串作为替换品。
特例,"%0"代表整个匹配。
2、如果"repl"是一个"table",每次匹配时都会用第一个捕获物作为键去查这张表。
如果"repl"是一个函数,则在每次匹配时都会以所有捕获物作为参数调用这个函数。
3、如果"pattern"中没有设定捕获,则默认捕获整个"pattern"。
4、如果"table"的查询结果或者函数的返回结果是一个字符串或是个数字时,
都将其作为替换品。而结果为"false"或"nil"时不作替换(即保留匹配前的原始串)。]]
print(string.gsub("Lua is cute", "cute", "great"))
--> Lua is great 1
print(string.gsub("all lii", "l", "x"))
--> axx xii 3
print(string.gsub("Lua is great", "perl", "tcl"))
--> Lua is great 0
print(string.gsub("hello world", "(%w+)", "%1 %1"))
--> hello hello world world 2
print(string.gsub("hello world", "%w+", "%0 %0", 1))
--> hello hello world 1
print(string.gsub("hello world from Lua", "(%w+)%s*(%w+)", "%2 %1"))
--> world hello Lua from 2
print(string.gsub("home = $HOME, user = $USER", "%$(%w+)", os.getenv))
--> home = /home/roberto, user = roberto 2
print(string.gsub("4+5 = $return 4+5$", "%$(.-)%$", function (s)
return load(s)()
end))
--> 4+5 = 9 1
local t = {name="lua", version="5.3"}
print(string.gsub("$name-$version.tar.gz", "%$(%w+)", t))
--> lua-5.3.tar.gz 2
--[[ string.match(s, pattern [, init])
返回字符串"s"中"pattern"所指定的捕获物。
如果"pattern"中没有设定捕获,则默认捕获整个"pattern"。
"init"可指定从字符串"s"的什么位置开始查找(可以为负数),默认为1。]]
print(string.match("home = $HOME, user = $USER", "%$(%w+)")) --> HOME
print(string.match("home = $HOME, user = $USER", "%$%w+")) --> $HOME
print(string.match("home = $HOME, user = $USER", "%$(%w+)", 15)) --> USER
--[[ string.gmatch(s, pattern)
返回一个"iterator"。
每次调用都会继续以匹配模式"pattern"对"s"做匹配,并返回所有捕获物。
如果"pattern"中没有设定捕获,则默认捕获整个"pattern"。]]
-- 遍历字符串中所有的单词。
s = "hello world from Lua"
for w in string.gmatch(s, "%a+") do
print(w)
end
-- 收集字符串中所有"key-value"对,存入"table"中。
t = {}
s = "from=world, to=Lua"
for k, v in string.gmatch(s, "(%w+)=(%w+)") do
t[k] = v
end
Q:如何编码与解码”URL encoding”?
A:”URL encoding”是”HTTP”协议用来发送”URL”中的参数进行的编码。这种编码将一些特殊字符(比如’=’、’&’、’+’)转换为”%XX”的十六进制形式的编码,然后将空格字符转换为’+’。比如将字符串"a+b = c"
编码为"a%2Bb+%3D+c"
。最后将参数名和参数值之间加一个’=’;在”name=value”对之间加一个’&’。比如一个”table”中存储的参数:
t = {name = "al", query = "a+b = c", q = "yes or no"}
会被编码为,
name=al&query=a%2Bb+%3D+c&q=yes+or+no
print("Encode: ")
function escape(s)
-- 将所有特殊字符替换为"%xx"的形式。
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
-- "name"与"value"之间以‘=‘分隔;"name=value"对之间以‘&‘分隔。
s = s .. "&" .. escape(k) .. "=" .. escape(v)
end
return string.sub(s, 2) -- 删除第一个多余的‘&‘。
end
t = {name = "al", query = "a+b = c", q="yes or no"}
s = encode(t)
print(s) --> name=al&query=a%2Bb+%3D+c&q=yes+or+no
print()
print("Decode: ")
function unescape (s)
s = string.gsub(s, "+", " ") -- 将所有"+"转换为空格。
-- 将所有"%XX"转换为ASCII字符。
s = string.gsub(s, "%%(%x%x)", function (h)
return string.char(tonumber(h, 16)) -- 十六进制数转为整数,整数再转为ASCII。
end)
return s
end
function decode(table, s)
-- 识别出每个"name-value"对,再进一步识别出"name"和"value"。
string.gsub(s, "([^&=]+)=([^&=]+)", function(name, value)
table[unescape(name)] = unescape(value)
end)
end
t1 = {}
decode(t1, s)
for i, v in pairs(t1) do print(i, v) end
--[[ result:
Encode:
name=al&query=a%2Bb+%3D+c&q=yes+or+no
Decode:
name al
query a+b = c
q yes or no]]
Q:其他一些实际的应用?
A:
_, count = string.gsub(str, " ", " ") -- 计算字符串中空格的数量。
_, count = string.gsub(str, "([AEIOUaeiou])", "%1") -- 计算字符串中元音的数量。
‘%(%s*%)‘ -- 匹配空的括号(括号中无内容或只含有空格)。
‘[_%a][_%w]*‘ -- 匹配Lua中所有的变量名。
‘[+-]?%d+‘ -- 匹配所有数值。
if string.find(s, "^%d") then ... end -- 字符串是否以数字开头。
if string.find(s, "^[+-]?%d+$") then ... end -- 字符串是否是一个整数。
string.gsub(str, "(.)(.)", "%2%1") -- 交换相邻两个字符。
--[[ 将"LaTeX"格式的字符串转换为"XML"格式的字符串。
"LaTeX": \command{some text}
"XML": <command>some text</command>]]
string.gsub(str, "\\(%a+){(.-)}", "<%1>%2</%1>")
string.gsub(s, "^%s*(.-)%s*$", "%1") -- "trim"字符串多余的空格。
-- 计算字符串中"$[]"内表达式的值。
string.gsub(s, "$(%b[])", function (x)
x = "return " .. string.sub(x, 2, -2) -- 跳过"["和"]"。
local f = load(x)
return f()
end)
附加:
1、将”LaTeX”格式的字符串转换为”XML”格式的字符串的实际例子,
s = "the \\quote{task} is to \\em{change} that."
-- 这里用"()"强制只保留"string.gsub()"的第一个返回值。
print((string.gsub(s, "\\(%a+){(.-)}", "<%1>%2</%1>")))
--> the <quote>task</quote> is to <em>change</em> that.
以上是关于快速掌握Lua 5.3 —— 字符串库的主要内容,如果未能解决你的问题,请参考以下文章
快速掌握Lua 5.3 —— 编写提供给Lua使用的C库函数的技巧