Lua 的 string 是 不可变的。它是字节序列(byte sequence),因此是编码无关的。
-- length
a = "hello"
#a --> 5
#"中文" --> 6 (UTF 8 terminal 下)
-- concat
a .. " world" --> "hello world"
a .. " world " .. 3 --> "hello world 3" (非 string 类型会被转为 string 再拼接)
-- escape sequences
> "hello\nworld"
hello
world
> '"string inside"'
"string inside"
> '\'abc\''
'abc'
-- \ddd 形式,ddd 是一个字节的 10 进制表示,范围 0~255
> "\97"
a
> "\097"
a
-- \xXX 形式
> "\x61"
a
-- \u{h ... h} 可以指定 unicode codepoint,Lua 会将其转换为 UTF-8 的字节序列
> "\u{4E2D}\u{6587}"
中文
-- 多行字符串 [[]]
-- 1. 第一个字符如果是换行,会被 Lua 忽略
-- 2. 在其中无法使用上述各种 escape,如 \xXX,\n 等
page = [[
<html>
<head>
<title>An HTML Page</title>
</head>
<body>
<a href="http://www.lua.org">Lua</a>
</body>
</html>
]]
-- 如果多行字符串中有非文本的字符,可以用这种方式来表达。
-- Lua 提供了 \z 用来连接多行字符串。
-- 我觉得这种形式并不优雅。不如 Python 的 """ """ 或者 JS 的 ``。
data = "\x00\x01\x02\x03\x04\x05\x06\x07\z
\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"
-- 字符串比较时,没有类型转换,比较的是字典序。
> "2" < "15"
false
string 标准库
Lua 的 string 是不可变的。因此 string 库中的函数都 不会修改传入的 string 参数。
Lua 的 string 标准库操作的是字节序列(按单字节来),因此你传多字节字符串不会有预期的效果:
> string.reverse("hello")
olleh
> string.reverse("中文")
??歸?
常用的操作:
> string.rep("abc", 3) --> abcabcabc
> string.reverse("A Long Line!") --> !eniL gnoL A
> string.lower("A Long Line!") --> a long line!
> string.upper("A Long Line!") --> A LONG LINE!
string.sub(s, i, j)
返回一串子字符串。注意 Lua 的 index 是 1-based,且 i
, j
是 inclusive 的:
> s = "[in brackets]"
> string.sub(s, 2, -2) --> in brackets
> string.sub(s, 1, 1) --> [
> string.sub(s, -1, -1) --> ]
-- 取前 size 位的子串
> size = 100
> string.sub(s, 1, size-1)
string.char()
string.byte()
将字符与其数字表示(numeric representation)互转:
print(string.char(97)) --> a
i = 99; print(string.char(i, i+1, i+2)) --> cde
print(string.byte("abc")) --> 97 (默认取第一个字符)
print(string.byte("abc", 2)) --> 98 (取第 2 个字符)
print(string.byte("abc", -1)) --> 99 (取最后一个字符)
-- 一种 pattern,生成 s 的数字表示的 list:
string.byte(s, 1, -1)
格式化字符串 string.format()
与 C 的 printf
一致:
> string.format("x = %d y = %d", 10, 20) --> x = 10 y = 20
> string.format("x = %x", 200) --> x = c8
> string.format("x = 0x%X", 200) --> x = 0xC8
> string.format("x = %f", 200) --> x = 200.000000
> tag, title = "h1", "a title"
> string.format("<%s>%s</%s>", tag, title, tag) --> <h1>a title</h1>
-- 控制数字的小数位
> string.format("pi = %.4f", math.pi) --> pi = 3.1416
-- 控制数字的按 0 填充
> d = 5; m = 11; y = 1990
> string.format("%02d/%02d/%04d", d, m, y) --> 05/11/1990
查找 string.find()
及全局替换(Global SUBstitution) string.gsub()
:
> string.find("hello world", "wor") --> 7 9
> start_index, end_index = string.find("hello world", "wor")
> end_index -->9
> string.find("hello world", "war") --> nil
> string.gsub("hello world", "l", ".") --> he..o wor.d 3
> string.gsub("hello world", "ll", "..") --> he..o world 1
> string.gsub("hello world", "a", ".") --> hello world 0
utf8 库
utf8 库提供了对 UTF8 字节序列的操作。
> utf8.len("résumé") --> 6
> utf8.len("中文") --> 2
-- Unicode codepoint 与 UTF-8 encoded byte sequence 互转
> utf8.char(114, 233, 115, 117, 109, 233) --> résumé
> utf8.codepoint("résumé", 6, 7) --> 109 233