字符串索引

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 上测试

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

最近更改 · 偏好设置
编辑 · 历史记录
最后编辑于 2019 年 2 月 16 日下午 12:50 GMT (差异)