string.sub与非英文字符的问题

时间:2014-03-02 15:29:00

标签: string unicode utf-8 lua lua-patterns

我需要获取文本变量的第一个字符。我通过以下简单方法之一实现了这一目标:

string.sub(someText,1,1)

someText:sub(1,1)

如果我执行以下操作,我希望将'ñ'作为第一个字母。但是,sub方法之一的结果是'Ã'

local someText = 'ñññññññ'
print('Test whole: '..someText) 
print('first char: '..someText:sub(1,1))
print('first char with .sub: '..string.sub(someText,1,1))

以下是控制台的结果:

2014-03-02 09:08:47.959 Corona Simulator[1701:507] Test whole: ñññññññ
2014-03-02 09:08:47.960 Corona Simulator[1701:507] first char: Ã
2014-03-02 09:08:47.960 Corona Simulator[1701:507] first char with .sub: Ã

似乎string.sub()函数正在以UTF-8编码返回的值。我只是尝试使用Corona SDK提供的utf8_decode()函数。它没有成功。模拟器表明该函数预期一个数字,但得到nil

我还搜索了网络,看看是否有其他人遇到过这个问题。我发现有很多关于Lua,Corona,Unicode和UTF-8的讨论,但我没有遇到任何可以解决这个特定问题的问题。

2 个答案:

答案 0 :(得分:4)

Lua字符串是8位干净的,这意味着Lua中的字符串是一个字节流。 UTF-8字符ñ有多个字节,但someText:sub(1,1)只返回第一个字节。

对于UTF-8编码,ASCII范围内的所有字符都具有与ASCII相同的表示形式,即小于128的单个字节。对于其他CodePoints,第一个字节为的字节序列在194-244范围内,连续字节在128-191范围内。

因此,您可以使用模式".[\128-\191]*"来匹配单个UTF-8 CodePoint(不是Grapheme):

for c in "ñññññññ":gmatch(".[\128-\191]*") do -- pretend the first string is in NFC
    print(c)
end

输出:

ñ
ñ
ñ
ñ
ñ
ñ
ñ

答案 1 :(得分:0)

关于使用的字符集:  只需了解您在自己的代码中加入哪些要求,并确保实际满意。  有各种典型的要求:

  • ASCII兼容(也就是任何字节< 128表示ASCII字符,所有ASCII字符都表示为自己)
  • 固定大小与可变宽度(可能是自同步)字符集
  • 没有嵌入的0字节

编写代码,以便您无需避免这些要求,并将其记录下来。

匹配单个UTF-8字符:确保UTF-8字符的含义。是字形还是CodePoint? AFAIK你需要完整的unicode表来进行字形匹配。你真的必须达到这个水平吗?