字串索引

lua-users home
wiki

在某種語言,例如 Python、C 與 Pascal 中,你可以寫下 a[5] 表示字串 a 的第 5 個(或第 6 個)字元。但 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) 會停止運作,並伴隨著錯誤訊息「傳給 sub 的第 2 個引數錯誤 (應為數字,但收到字串)」已在 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
| @bckpol 我沒有遇到這樣的問題

但字串,比如 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 (差異)