提取 Lua 中由 Unicode 空格和控制字符分割的单词
Extract words in Lua split by Unicode spaces and control characters
我对在某些 Unicode 控制字符和空格之间提取字符串单元的纯Lua(即没有外部 Unicode 库)解决方案很感兴趣。我想用作分隔符的代码点是:
0000-0020
007f-00a0
00ad
1680
2000-200a
2028-2029
202f
205f
3000
我知道如何访问字符串中的代码点,例如:
> for i,c in utf8.codes("é$ \tπ") do print(c) end
233
36
32
9
960
128515
但我不确定如何“跳过”空格和制表符并将其他代码点重新构造为字符串本身。在上面的示例中,我想做的是删除 32 和 9,然后可能使用 utf8.char(233, 36) 和 utf8.char(960, 128515) 以某种方式获得 ["é$" , "π"].
似乎将所有内容都放入一个 table 的数字中,然后使用 for 循环和 if 语句煞费苦心地遍历 table 似乎会奏效,但有没有更好的方法?我调查了 string:gmatch,但这似乎需要在我想要的每个范围之外制作 utf8 序列,并且不清楚该模式会是什么样子。
有没有一种惯用的方法来提取空格之间的字符串?还是我必须手动破解 table 个代码点? gmatch
不查找任务。或者是?
would require painstakingly generating the utf8 encodings for all code points at each end of the range.
是的。但当然不是手动。
local function range(from, to)
assert(utf8.codepoint(from) // 64 == utf8.codepoint(to) // 64)
return from:sub(1,-2).."["..from:sub(-1).."-"..to:sub(-1).."]"
end
local function split_unicode(s)
for w in s
:gsub("[[=10=]-\x1F\x7F]", " ")
:gsub("\u{00a0}", " ")
:gsub("\u{00ad}", " ")
:gsub("\u{1680}", " ")
:gsub(range("\u{2000}", "\u{200a}"), " ")
:gsub(range("\u{2028}", "\u{2029}"), " ")
:gsub("\u{202f}", " ")
:gsub("\u{205f}", " ")
:gsub("\u{3000}", " ")
:gmatch"%S+"
do
print(w)
end
end
测试:
split_unicode("@[=11=]@\t@\x1F@\x7F@\u{00a0}@\u{00ad}@\u{1680}@\u{2000}@\u{2005}@\u{200a}@\u{2028}@\u{2029}@\u{202f}@\u{205f}@\u{3000}@")
我对在某些 Unicode 控制字符和空格之间提取字符串单元的纯Lua(即没有外部 Unicode 库)解决方案很感兴趣。我想用作分隔符的代码点是:
0000-0020 007f-00a0 00ad 1680 2000-200a 2028-2029 202f 205f 3000
我知道如何访问字符串中的代码点,例如:
> for i,c in utf8.codes("é$ \tπ") do print(c) end
233
36
32
9
960
128515
但我不确定如何“跳过”空格和制表符并将其他代码点重新构造为字符串本身。在上面的示例中,我想做的是删除 32 和 9,然后可能使用 utf8.char(233, 36) 和 utf8.char(960, 128515) 以某种方式获得 ["é$" , "π"].
似乎将所有内容都放入一个 table 的数字中,然后使用 for 循环和 if 语句煞费苦心地遍历 table 似乎会奏效,但有没有更好的方法?我调查了 string:gmatch,但这似乎需要在我想要的每个范围之外制作 utf8 序列,并且不清楚该模式会是什么样子。
有没有一种惯用的方法来提取空格之间的字符串?还是我必须手动破解 table 个代码点? gmatch
不查找任务。或者是?
would require painstakingly generating the utf8 encodings for all code points at each end of the range.
是的。但当然不是手动。
local function range(from, to)
assert(utf8.codepoint(from) // 64 == utf8.codepoint(to) // 64)
return from:sub(1,-2).."["..from:sub(-1).."-"..to:sub(-1).."]"
end
local function split_unicode(s)
for w in s
:gsub("[[=10=]-\x1F\x7F]", " ")
:gsub("\u{00a0}", " ")
:gsub("\u{00ad}", " ")
:gsub("\u{1680}", " ")
:gsub(range("\u{2000}", "\u{200a}"), " ")
:gsub(range("\u{2028}", "\u{2029}"), " ")
:gsub("\u{202f}", " ")
:gsub("\u{205f}", " ")
:gsub("\u{3000}", " ")
:gmatch"%S+"
do
print(w)
end
end
测试:
split_unicode("@[=11=]@\t@\x1F@\x7F@\u{00a0}@\u{00ad}@\u{1680}@\u{2000}@\u{2005}@\u{200a}@\u{2028}@\u{2029}@\u{202f}@\u{205f}@\u{3000}@")