提取 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}@")