Lua 字符串庫包含很多強大的字符操作函數(shù)。字符串庫中的所有函數(shù)都導(dǎo)出在模塊 string 中。在 Lua 5.1 中,它還將這些函數(shù)導(dǎo)出作為 string 類型的方法。這樣假設(shè)要返回一個字符串轉(zhuǎn)的大寫形式,可以寫成 ans = string.upper(s)
, 也能寫成 ans = s:upper()
。為了避免與之前版本不兼容,此處使用前者。
Lua 字符串總是由字節(jié)構(gòu)成的。Lua 核心并不嘗試?yán)斫饩唧w的字符集編碼(比如 GBK 和 UTF-8 這樣的多字節(jié)字符編碼)。
需要特別注意的一點是,Lua 字符串內(nèi)部用來標(biāo)識各個組成字節(jié)的下標(biāo)是從 1 開始的,這不同于像 C 和 Perl 這樣的編程語言。這樣數(shù)字符串位置的時候再也不用調(diào)整,對于非專業(yè)的開發(fā)者來說可能也是一個好事情,string.sub(str, 3, 7) 直接表示從第三個字符開始到第七個字符(含)為止的子串。
返回字符 s[i]、s[i + 1]、s[i + 2]、······、s[j] 所對應(yīng)的 ASCII 碼。i
的默認(rèn)值為 1,即第一個字節(jié),j
的默認(rèn)值為 i 。
示例代碼
print(string.byte("abc", 1, 3))
print(string.byte("abc", 3)) -- 缺少第三個參數(shù),第三個參數(shù)默認(rèn)與第二個相同,此時為 3
print(string.byte("abc")) -- 缺少第二個和第三個參數(shù),此時這兩個參數(shù)都默認(rèn)為 1
-->output
97 98 99
99
97
由于 string.byte
只返回整數(shù),而并不像 string.sub
等函數(shù)那樣(嘗試)創(chuàng)建新的 Lua 字符串,
因此使用 string.byte
來進行字符串相關(guān)的掃描和分析是最為高效的,尤其是在被 LuaJIT 2 所 JIT 編譯之后。
接收 0 個或更多的整數(shù)(整數(shù)范圍:0~255),返回這些整數(shù)所對應(yīng)的 ASCII 碼字符組成的字符串。當(dāng)參數(shù)為空時,默認(rèn)是一個 0。
示例代碼
print(string.char(96, 97, 98))
print(string.char()) -- 參數(shù)為空,默認(rèn)是一個0,
-- 你可以用string.byte(string.char())測試一下
print(string.char(65, 66))
--> output
`ab
AB
此函數(shù)特別適合從具體的字節(jié)構(gòu)造出二進制字符串。這經(jīng)常比使用 table.concat
函數(shù)和 ..
連接運算符更加高效。
接收一個字符串 s,返回一個把所有小寫字母變成大寫字母的字符串。
示例代碼
print(string.upper("Hello Lua")) -->output HELLO LUA
接收一個字符串 s,返回一個把所有大寫字母變成小寫字母的字符串。
示例代碼
print(string.lower("Hello Lua")) -->output hello lua
接收一個字符串,返回它的長度。
示例代碼
print(string.len("hello lua")) -->output 9
使用此函數(shù)是不推薦的。應(yīng)當(dāng)總是使用 #
運算符來獲取 Lua 字符串的長度。
由于 Lua 字符串的長度是專門存放的,并不需要像 C 字符串那樣即時計算,因此獲取字符串長度的操作總是 O(1)
的時間復(fù)雜度。
在 s 字符串中第一次匹配 p 字符串。若匹配成功,則返回 p 字符串在 s 字符串中出現(xiàn)的開始位置和結(jié)束位置;若匹配失敗,則返回 nil。 第三個參數(shù) init 默認(rèn)為 1,并且可以為負(fù)整數(shù),當(dāng) init 為負(fù)數(shù)時,表示從 s 字符串的 string.len(s) + init 索引處開始向后匹配字符串 p 。 第四個參數(shù)默認(rèn)為 false,當(dāng)其為 true 時,只會把 p 看成一個字符串對待。
示例代碼
local find = string.find
print(find("abc cba", "ab"))
print(find("abc cba", "ab", 2)) -- 從索引為2的位置開始匹配字符串:ab
print(find("abc cba", "ba", -1)) -- 從索引為7的位置開始匹配字符串:ba
print(find("abc cba", "ba", -3)) -- 從索引為6的位置開始匹配字符串:ba
print(find("abc cba", "(%a+)", 1)) -- 從索引為1處匹配最長連續(xù)且只含字母的字符串
print(find("abc cba", "(%a+)", 1, true)) --從索引為1的位置開始匹配字符串:(%a+)
-->output
1 2
nil
nil
6 7
1 3 abc
nil
對于 LuaJIT 這里有個性能優(yōu)化點,對于 string.find 方法,當(dāng)只有字符串查找匹配時,是可以被 JIT 編譯器優(yōu)化的,有關(guān) JIT 可以編譯優(yōu)化清單,大家可以參考 http://wiki.luajit.org/NYI,性能提升是非常明顯的,通常是 100 倍量級。這里有個的例子,大家可以參考 https://groups.google.com/forum/m/#!topic/openresty-en/rwS88FGRsUI。
按照格式化參數(shù) formatstring,返回后面 ...
內(nèi)容的格式化版本。編寫格式化字符串的規(guī)則與標(biāo)準(zhǔn) c 語言中 printf 函數(shù)的規(guī)則基本相同:它由常規(guī)文本和指示組成,這些指示控制了每個參數(shù)應(yīng)放到格式化結(jié)果的什么位置,及如何放入它們。一個指示由字符 %
加上一個字母組成,這些字母指定了如何格式化參數(shù),例如 d
用于十進制數(shù)、x
用于十六進制數(shù)、o
用于八進制數(shù)、f
用于浮點數(shù)、s
用于字符串等。在字符 %
和字母之間可以再指定一些其他選項,用于控制格式的細(xì)節(jié)。
示例代碼
print(string.format("%.4f", 3.1415926)) -- 保留4位小數(shù)
print(string.format("%d %x %o", 31, 31, 31))-- 十進制數(shù)31轉(zhuǎn)換成不同進制
d = 29; m = 7; y = 2015 -- 一行包含幾個語句,用;分開
print(string.format("%s %02d/%02d/%d", "today is:", d, m, y))
-->output
3.1416
31 1f 37
today is: 29/07/2015
在字符串 s 中匹配(模式)字符串 p,若匹配成功,則返回目標(biāo)字符串中與模式匹配的子串;否則返回 nil。第三個參數(shù) init 默認(rèn)為 1,并且可以為負(fù)整數(shù),當(dāng) init 為負(fù)數(shù)時,表示從 s 字符串的 string.len(s) + init 索引處開始向后匹配字符串 p。
示例代碼
print(string.match("hello lua", "lua"))
print(string.match("lua lua", "lua", 2)) --匹配后面那個lua
print(string.match("lua lua", "hello"))
print(string.match("today is 27/7/2015", "%d+/%d+/%d+"))
-->output
lua
lua
nil
27/7/2015
string.match
目前并不能被 JIT 編譯,應(yīng) 盡量 使用 ngx_lua 模塊提供的 ngx.re.match
等接口。
返回一個迭代器函數(shù),通過這個迭代器函數(shù)可以遍歷到在字符串 s 中出現(xiàn)模式串 p 的所有地方。
示例代碼
s = "hello world from Lua"
for w in string.gmatch(s, "%a+") do --匹配最長連續(xù)且只含字母的字符串
print(w)
end
-->output
hello
world
from
Lua
t = {}
s = "from=world, to=Lua"
for k, v in string.gmatch(s, "(%a+)=(%a+)") do --匹配兩個最長連續(xù)且只含字母的
t[k] = v --字符串,它們之間用等號連接
end
for k, v in pairs(t) do
print (k,v)
end
-->output
to Lua
from world
此函數(shù)目前并不能被 LuaJIT 所 JIT 編譯,而只能被解釋執(zhí)行。應(yīng) 盡量 使用 ngx_lua 模塊提供的 ngx.re.gmatch
等接口。
返回字符串 s 的 n 次拷貝。
示例代碼
print(string.rep("abc", 3)) --拷貝3次"abc"
-->output abcabcabc
返回字符串 s 中,索引 i 到索引 j 之間的子字符串。當(dāng) j 缺省時,默認(rèn)為 -1,也就是字符串 s 的最后位置。i 可以為負(fù)數(shù)。當(dāng)索引 i 在字符串 s 的位置在索引 j 的后面時,將返回一個空字符串。
示例代碼
print(string.sub("Hello Lua", 4, 7))
print(string.sub("Hello Lua", 2))
print(string.sub("Hello Lua", 2, 1)) --看到返回什么了嗎
print(string.sub("Hello Lua", -3, -1))
-->output
lo L
ello Lua
Lua
如果你只是想對字符串中的單個字節(jié)進行檢查,使用 string.char
函數(shù)通常會更為高效。
將目標(biāo)字符串 s 中所有的子串 p 替換成字符串 r??蛇x參數(shù) n,表示限制替換次數(shù)。返回值有兩個,第一個是被替換后的字符串,第二個是替換了多少次。
示例代碼
print(string.gsub("Lua Lua Lua", "Lua", "hello"))
print(string.gsub("Lua Lua Lua", "Lua", "hello", 2)) --指明第四個參數(shù)
-->output
hello hello hello 3
hello hello Lua 2
此函數(shù)不能為 LuaJIT 所 JIT 編譯,而只能被解釋執(zhí)行。一般我們推薦使用 ngx_lua 模塊提供的 ngx.re.gsub
函數(shù)。
接收一個字符串 s,返回這個字符串的反轉(zhuǎn)。
示例代碼
print(string.reverse("Hello Lua")) --> output: auL olleH