快速掌握Lua 5.3 —— 字符串库 (2)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/VermillionTear/article/details/50700299

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.

猜你喜欢

转载自blog.csdn.net/VermillionTear/article/details/50700299
5.3