字符串索引

lua-users home
wiki

在某些语言中,例如 Python、C 和 Pascal,您可以使用 a[5] 来获取字符串 a 的第五个(或可能是第六个)字符。Lua 不行。您必须编写 a:sub(5,5)string.sub(a,5,5)。我们能做些什么吗?

从 Lua 5.1 开始,可以。因此

getmetatable('').__index = function(str,i) return string.sub(str,i,i) end
-- demo
a='abcdef'
return a[4]      --> d

| 在此之后我遇到了问题:代码 s:sub(2) 在使用时停止工作并出现错误 "bad argument #2 to 'sub' (number expected, got string)" 已在 lua 5.2.4 /d9k 上测试过 /d9k

local strdefi=getmetatable('').__index
getmetatable('').__index=function(str,i) if type(i) == "number" then
    return string.sub(str,i,i)
    else return strdefi[i] end end
| 没有遇到这些问题 @bckpkol

但是子字符串呢?例如 a[3,5]?不行,这是非法的。我们必须改用 __call 元方法。

getmetatable('').__call = string.sub
-- demo
a='abcdef'
return a(3,5)    --> cde
return a(4)      --> def -- equivalent to a(4,-1)

让我们做得更花哨一点,并实现 Luiz 本人的建议。[1]

getmetatable('').__index = function(str,i) return string.sub(str,i,i) end
getmetatable('').__call = function(str,i,j)  
  if type(i)~='table' then return string.sub(str,i,j) 
    else local t={} 
    for k,v in ipairs(i) do t[k]=string.sub(str,v,v) end
    return table.concat(t)
    end
  end
-- demo
a='abcdef'
return a[4]       --> d
return a(3,5)     --> cde 
return a{1,-4,5}  --> ace
所以您看到了:方括号用于单字节子字符串,圆括号用于从-到子字符串,花括号用于选择字节。

注意:使用这个简单的 __index 方法,您将失去对字符串调用方法的能力,例如 a:match('abc')。您需要修改 __index 如下:

getmetatable('').__index = function(str,i)
  if type(i) == 'number' then
    return string.sub(str,i,i)
  else
    return string[i]
  end
end

如果您不喜欢这样,可以省略 __index 的重定义,并使用 a{4} 而不是 a[4]

字符与字节

请始终记住,这些索引函数选择的是字节,而不是字符。例如,UTF-8 字符占用可变数量的字节:请参阅讨论 ValidateUnicodeString

Lua = 'Lua'
print (Lua(1,3))    -->   L

RecentChanges · preferences
编辑 · 历史
最后编辑于 2019 年 2 月 16 日上午 6:50 GMT (差异)