【发布时间】:2019-09-09 17:20:39
【问题描述】:
我正在重写一个 awk 程序,该程序格式化要输出到状态栏的字符串。我不是一个程序员,只是一个业余爱好者,在我遇到的任何停机时间都试图学习。
截断任何非 ASCII 字符时,例如西里尔文 (utf8) 会导致输出损坏,并显示为一系列问号。
Ouverture Il Ritorno dall'Estero op. 89 / Mendelsshon / Великие �… / 320 kb/s
string.len 和 # 计数字节,而不是字符。并且单个西里尔字符被计为 2 个字节而不是 1 个。这显然会使截断复杂化。幸运的是,Lua 5.3 包含 utf8 library、wiki on unicode support 以简化非 acsii 字符的使用。我修改了“缩短”功能以使用 utf8.len 以获得准确的 character 截断计数,但问题仍然存在。
--from penlight library, use utf8.len, not string.len
function shorten(s,w)
local ellipsis = "…"
local n_ellipsis = utf8.len(ellipsis)
assert_string(1,s)
if utf8.len(s) > w then
return s:sub(1,w-n_ellipsis) .. ellipsis
end
return s
end
通过进一步阅读,我了解到在需要截断时应使用 utf8.offset。
您应该在需要处理不是您自己编写或可能包含非 ASCII 或非英文字符的文本的任何地方使用这些函数。如果您截断不在整个代码点之间的字节索引处的字符串,您最终将得到一个无效的 UTF-8 字符串,该字符串可能无法正确呈现或无法存储在 DataStore 中。
如果你在索引处截断字符串,你应该使用 string.sub 和 utf8.offset 给出的字节索引。
我一直在试图弄清楚如何使用utf8.offset 来获取所需的字节索引,但到目前为止成功率为零。如果进一步的上下文有帮助,这是我的 wip full script
任何提示、代码、批评等将不胜感激。
【问题讨论】:
-
return s:sub(1, utf8.offset(s, w - n_ellipsis + 1) - 1) .. ellipsis -
非常感谢@EgorSkriptunoff。这确实解决了这个问题:) 也比我预期的要简单一些。马上。
-
请从问题中删除您的解决方案并将其作为答案发布。