Lua中的字符串是不可变的,这意味着一旦创建就不能修改。字符串在Lua中是值类型,但内部使用引用计数和字符串驻留(string interning)来优化内存使用。相同的字符串字面量会共享同一个内存对象,这提高了比较效率和内存利用率。字符串长度信息存储在字符串对象中,因此获取长度是O(1)操作。
-- 字符串长度
local str = "Hello Lua"
print(#str) -- 9
print(string.len(str)) -- 9
-- 字符串连接
local s1 = "Hello"
local s2 = "World"
print(s1 .. " " .. s2) -- Hello World
-- 字符串重复
print(string.rep("Lua", 3)) -- LuaLuaLua
print(string.rep("-", 20)) -- --------------------
-- 字符串比较
local str1 = "apple"
local str2 = "banana"
print(str1 < str2) -- true (按字典序比较)
print(str1 == str1) -- true
-- 多行字符串
local multiline = [[
第一行
第二行
第三行
]]
print(multiline)
-- 字符串转义序列
local escaped = "Hello\nWorld\t\"Lua\""
print(escaped)
-- UTF-8字符处理(Lua 5.3+)
local utf8str = "你好世界"
print(#utf8str) -- 12 (字节数)
-- 使用utf8库处理Unicode字符
if utf8 then
print(utf8.len(utf8str)) -- 4 (字符数)
for i, c in utf8.codes(utf8str) do
print(i, utf8.char(c))
end
end
local str = "Hello Lua"
-- 转大写
print(string.upper(str)) -- HELLO LUA
-- 转小写
print(string.lower(str)) -- hello lua
-- 首字母大写
function capitalize(s)
return string.upper(string.sub(s, 1, 1)) .. string.sub(s, 2)
end
print(capitalize("lua")) -- Lua
local text = "Hello Lua, Lua is great!"
-- string.find(str, pattern, [init, [plain]])
local start, finish = string.find(text, "Lua")
print(start, finish) -- 7 9
-- 从指定位置开始查找
local start2, finish2 = string.find(text, "Lua", 10)
print(start2, finish2) -- 12 14
-- 纯文本查找(不使用模式)
local s, f = string.find(text, ".", 1, true)
print(s, f) -- 查找点号
-- 检查字符串是否包含子串
if string.find(text, "great") then
print("找到了great")
end
local str = "Hello Lua"
-- string.sub(str, start, [end])
print(string.sub(str, 1, 5)) -- Hello
print(string.sub(str, 7)) -- Lua
print(string.sub(str, -3)) -- Lua (负数从末尾开始)
print(string.sub(str, 1, -5)) -- Hello
-- 获取单个字符
print(string.sub(str, 1, 1)) -- H
print(string.sub(str, -1)) -- a
local text = "I love Lua, Lua is great"
-- string.gsub(str, pattern, repl, [n])
local result, count = string.gsub(text, "Lua", "Python")
print(result) -- I love Python, Python is great
print(count) -- 2 (替换次数)
-- 限制替换次数
local result2 = string.gsub(text, "Lua", "Python", 1)
print(result2) -- I love Python, Lua is great
-- 使用函数替换
local str = "hello world"
local result3 = string.gsub(str, "%w+", string.upper)
print(result3) -- HELLO WORLD
-- 分割字符串
function split(str, delimiter)
local result = {}
local pattern = string.format("([^%s]+)", delimiter)
for word in string.gmatch(str, pattern) do
table.insert(result, word)
end
return result
end
local text = "apple,banana,orange"
local fruits = split(text, ",")
for i, fruit in ipairs(fruits) do
print(i, fruit)
end
-- 输出:
-- 1 apple
-- 2 banana
-- 3 orange
Lua的模式匹配系统虽然不如正则表达式强大,但更轻量且高效。模式使用%作为转义字符,而不是\。模式匹配是基于有限状态机的实现,对于大多数常见任务已经足够。Lua 5.3+还引入了utf8模式,可以正确处理Unicode字符。
-- 模式匹配字符类
-- %a 字母
-- %d 数字
-- %s 空白字符
-- %w 字母和数字
-- %p 标点符号
-- %c 控制字符
-- %x 十六进制数字
-- %z 表示0的字符
local str = "Phone: 123-456-7890"
-- 提取数字
for num in string.gmatch(str, "%d+") do
print(num)
end
-- 输出: 123 456 7890
-- 提取单词
local text = "Hello Lua World"
for word in string.gmatch(text, "%a+") do
print(word)
end
-- 输出: Hello Lua World
-- 匹配邮箱
local email = "user@example.com"
if string.match(email, "%w+@%w+%.%w+") then
print("有效的邮箱")
end
-- 模式修饰符
-- + 匹配前一字符1次或多次
-- * 匹配前一字符0次或多次
-- - 匹配前一字符0次或多次(最短匹配)
-- ? 匹配前一字符0次或1次
-- 最短匹配示例
local html = "ContentMore"
local short = string.match(html, ".-")
print(short) -- Content
local long = string.match(html, ".*")
print(long) -- ContentMore
-- 捕获组
local date = "2024-01-15"
local year, month, day = string.match(date, "(%d+)-(%d+)-(%d+)")
print(year, month, day) -- 2024 01 15
-- 使用string.match提取信息
local url = "https://www.example.com/path/to/page"
local protocol, domain, path = string.match(url, "^(%w+)://([^/]+)(.*)$")
print(protocol) -- https
print(domain) -- www.example.com
print(path) -- /path/to/page
-- 匹配IP地址
local ip = "192.168.1.1"
if string.match(ip, "^%d+%.%d+%.%d+%.%d+$") then
print("有效的IP地址格式")
end
-- 匹配十六进制颜色
local color = "#FF5733"
if string.match(color, "^#%x%x%x%x%x%x$") then
print("有效的十六进制颜色")
end
-- 匹配日期(YYYY-MM-DD)
local dateStr = "2024-01-15"
if string.match(dateStr, "^%d%d%d%d-%d%d-%d%d$") then
print("有效的日期格式")
end
-- string.format(formatstring, ...)
local name = "张三"
local age = 25
local score = 95.5
-- 基本格式化
print(string.format("姓名: %s, 年龄: %d", name, age))
-- 数字格式化
print(string.format("%.2f", score)) -- 95.50 (保留2位小数)
print(string.format("%d", 123)) -- 123
print(string.format("%5d", 123)) -- " 123" (宽度5)
print(string.format("%05d", 123)) -- "00123" (补零)
-- 十六进制
print(string.format("%x", 255)) -- ff
print(string.format("%X", 255)) -- FF
-- 科学计数法
print(string.format("%e", 1000)) -- 1.000000e+03
-- string.byte(str, [i, [j]])
local str = "ABC"
print(string.byte(str, 1)) -- 65 (A的ASCII码)
print(string.byte(str, 2)) -- 66 (B的ASCII码)
local a, b, c = string.byte(str, 1, 3)
print(a, b, c) -- 65 66 67
-- string.char(...)
print(string.char(65, 66, 67)) -- ABC
print(string.char(72, 101, 108, 108, 111)) -- Hello
-- 字符串反转
function reverse(str)
return string.reverse(str)
end
print(reverse("Hello")) -- olleH
-- 去除首尾空格
function trim(str)
return string.gsub(str, "^%s*(.-)%s*$", "%1")
end
print(trim(" Hello Lua ")) -- "Hello Lua"
-- 去除所有空格
function removeSpaces(str)
return string.gsub(str, "%s+", "")
end
print(removeSpaces("H e l l o")) -- "Hello"
-- 去除左侧空格
function ltrim(str)
return string.gsub(str, "^%s+", "")
end
-- 去除右侧空格
function rtrim(str)
return string.gsub(str, "%s+$", "")
end
-- 字符串填充
function padLeft(str, len, char)
char = char or " "
return string.rep(char, len - #str) .. str
end
function padRight(str, len, char)
char = char or " "
return str .. string.rep(char, len - #str)
end
print(padLeft("42", 5, "0")) -- 00042
print(padRight("Lua", 10, "-")) -- Lua-------
-- 字符串居中
function center(str, len, char)
char = char or " "
local padLen = len - #str
local leftPad = math.floor(padLen / 2)
local rightPad = padLen - leftPad
return string.rep(char, leftPad) .. str .. string.rep(char, rightPad)
end
print(center("Lua", 10, "*")) -- ***Lua****
-- 判断字符串是否为回文
function isPalindrome(str)
-- 移除非字母字符并转为小写
local clean = string.gsub(string.lower(str), "%W", "")
return clean == string.reverse(clean)
end
print(isPalindrome("A man, a plan, a canal: Panama")) -- true
print(isPalindrome("Hello")) -- false
-- 统计字符频率
function charFrequency(str)
local freq = {}
for char in string.gmatch(str, ".") do
freq[char] = (freq[char] or 0) + 1
end
return freq
end
local freq = charFrequency("Hello World")
for char, count in pairs(freq) do
print(string.format("'%s': %d", char, count))
end
-- 驼峰命名转下划线命名
function camelToSnake(str)
return string.gsub(str, "%u", function(c)
return "_" .. string.lower(c)
end)
end
print(camelToSnake("camelCaseString")) -- camel_case_string
-- 下划线命名转驼峰命名
function snakeToCamel(str)
return string.gsub(str, "_%w", function(c)
return string.upper(string.sub(c, 2))
end)
end
print(snakeToCamel("snake_case_string")) -- snakeCaseString
-- 字符串压缩(简单的RLE压缩)
function compress(str)
local result = {}
local count = 1
local prev = string.sub(str, 1, 1)
for i = 2, #str do
local char = string.sub(str, i, i)
if char == prev and count < 9 then
count = count + 1
else
table.insert(result, count .. prev)
prev = char
count = 1
end
end
table.insert(result, count .. prev)
return table.concat(result)
end
function decompress(str)
local result = {}
for count, char in string.gmatch(str, "(%d)(.)") do
table.insert(result, string.rep(char, tonumber(count)))
end
return table.concat(result)
end
local original = "AAABBBCCDDDD"
local compressed = compress(original)
local decompressed = decompress(compressed)
print("Original:", original)
print("Compressed:", compressed)
print("Decompressed:", decompressed)
-- 字符串相似度(Levenshtein距离)
function levenshtein(str1, str2)
local len1, len2 = #str1, #str2
local matrix = {}
for i = 0, len1 do
matrix[i] = {[0] = i}
end
for j = 0, len2 do
matrix[0][j] = j
end
for i = 1, len1 do
for j = 1, len2 do
local cost = string.sub(str1, i, i) == string.sub(str2, j, j) and 0 or 1
matrix[i][j] = math.min(
matrix[i-1][j] + 1,
matrix[i][j-1] + 1,
matrix[i-1][j-1] + cost
)
end
end
return matrix[len1][len2]
end
print(levenshtein("kitten", "sitting")) -- 3
print(levenshtein("Lua", "Lua")) -- 0
-- 字符串模板引擎
function template(tmpl, vars)
return string.gsub(tmpl, "%{(%w+)%}", function(key)
return vars[key] or ""
end)
end
local html = template("Hello, {name}!
Age: {age}
", {
name = "张三",
age = 25
})
print(html)