源端这套 Lua 是 Lua4,字符串库默认还是老写法(strlen/strsub/strfind/...),写脚本很不顺手。Lua5 里大家都习惯 string.len/string.sub/string.find/string.gsub 这一套,我就直接做了个增量兼容层:
不改原逻辑、不动旧脚本,只是在 Lua4 里把 Lua5 常用的 string.xxx 挂进去。
一句话:
老脚本照跑,新脚本可以直接按 Lua5 风格写 string.xxx()。
0)我新增了哪些函数(Lua5 风格)
| 新增函数 |
作用 |
string.len(s) |
字符串长度 |
string.sub(s, i [, j]) |
截取子串 |
string.lower(s) |
转小写 |
string.upper(s) |
转大写 |
string.rep(s, n) |
重复字符串 |
string.byte(s [, i [, j]]) |
取字节(支持区间,多返回) |
string.char(...) |
字节转字符串 |
string.find(s, p [, init [, plain]]) |
查找(支持 plain 纯文本) |
string.gsub(s, p, repl [, n]) |
替换(repl 支持 string/function/table) |
string.format(fmt, ...) |
格式化 |
1)string.len / sub / lower / upper / rep
local s = "AbCdef"
print(string.len(s)) -- 6
print(string.sub(s, 2, 4)) -- bCd
print(string.lower(s)) -- abcdef
print(string.upper(s)) -- ABCDEF
print(string.rep("-", 8)) -- --------
2)string.byte / string.char
string.byte(s [,i [,j]])
- 不传 i/j:返回第 1 个字节
- 传 i:返回第 i 个字节
- 传 i,j:返回区间多个字节(多返回值,Lua5 风格)
print(string.byte("ABC")) -- 65
print(string.byte("ABC", 2)) -- 66
local a,b,c = string.byte("ABC", 1, 3)
print(a,b,c) -- 65 66 67
string.char(...)
print(string.char(65,66,67)) -- ABC
3)string.find(支持 plain=1)
返回值:
- 找到:
startIndex, endIndex(如果有捕获还会多返回捕获)
- 找不到:
nil
local i,j = string.find("hello world", "world")
print(i,j) -- 7 11
plain = 1(纯文本查找)
Lua4 没 boolean,我这里按约定用 1/0:
local i2,j2 = string.find("a+b=c", "a+b", 1, 1) -- plain=1
print(i2,j2) -- 1 3
模式 + 捕获
local x,y,cap = string.find("id=12345", "id=(%d+)")
print(x,y,cap) -- 1 8 12345
4)string.gsub(重点:支持 table 替换)
返回:newString, replaceCount
4.1 普通替换
local r,n = string.gsub("hello hello", "hello", "hi")
print(r,n) -- hi hi 2
4.2 捕获替换(%1 %2)
local r2,n2 = string.gsub("name=Tom age=18", "(%w+)=(%w+)", "%1:[%2]")
print(r2,n2) -- name:[Tom] age:[18] 2
4.3 函数替换
local r3,n3 = string.gsub("hp=99 mp=20", "(%d+)", function(num)
return tostring(tonumber(num) + 1)
end)
print(r3,n3) -- hp=100 mp=21 2
4.4 table 替换(Lua5 风格)
规则(我这边实现就是这么走的):
- pattern 有捕获:用第一个捕获当 key 去表里查
- pattern 没捕获:用整段匹配内容当 key 去表里查
- 查不到 key:保留原字符串
local map = { foo="苹果", bar="香蕉" }
local r4,n4 = string.gsub("foo=1;bar=2;baz=3", "(%w+)=(%d+)", map)
print(r4,n4) -- 苹果=1;香蕉=2;baz=3 3
print(string.format("name=%s hp=%d pi=%.2f hex=%X", "player", 100, 3.14159, 255))
-- name=player hp=100 pi=3.14 hex=FF
6)一段完整自测脚本(我就是用这个验的)
print("=== string.len/sub/lower/upper/rep ===")
local s = "AbCdef"
print(string.len(s))
print(string.sub(s, 2, 4))
print(string.lower(s))
print(string.upper(s))
print(string.rep("-", 8))
print("\n=== string.byte/char ===")
local a,b,c = string.byte("ABC", 1, 3)
print(a,b,c)
print(string.char(a,b,c))
print("\n=== string.find ===")
local i,j = string.find("hello world", "world")
print(i,j)
local i2,j2 = string.find("a+b=c", "a+b", 1, 1) -- plain=1
print(i2,j2)
local x,y,cap = string.find("id=12345", "id=(%d+)")
print(x,y,cap)
print("\n=== string.gsub ===")
local r1,n1 = string.gsub("hello hello", "hello", "hi")
print(r1,n1)
local r2,n2 = string.gsub("name=Tom age=18", "(%w+)=(%w+)", "%1:[%2]")
print(r2,n2)
local r3,n3 = string.gsub("hp=99 mp=20", "(%d+)", function(num)
return tostring(tonumber(num) + 1)
end)
print(r3,n3)
local map = { foo="苹果", bar="香蕉" }
local r4,n4 = string.gsub("foo=1;bar=2;baz=3", "(%w+)=(%d+)", map)
print(r4,n4)
print("\n=== string.format ===")
print(string.format("name=%s hp=%d pi=%.2f hex=%X", "player", 100, 3.14159, 255))
对应输出(参考)
=== string.len/sub/lower/upper/rep ===
6
bCd
abcdef
ABCDEF
--------
=== string.byte/char ===
65 66 67
ABC
=== string.find ===
7 11
1 3
1 8 12345
=== string.gsub ===
hi hi 2
name:[Tom] age:[18] 2
hp=100 mp=21 2
苹果=1;香蕉=2;baz=3 3
=== string.format ===
name=player hp=100 pi=3.14 hex=FF
结尾一句
这套 string 兼容层我就是奔着“不动旧脚本”去做的:
旧脚本照旧用老函数,新脚本统一按 Lua5 写 string.xxx(),可读性直接提升一大截。