2009-05-06 65 views
67

我在Lua中有一個字符串,並且想要迭代它中的單個字符。但是,沒有代碼我試過的作品和官方手冊只顯示瞭如何查找和替換子:(如何迭代Lua字符串中的單個字符?

str = "abcd" 
for char in str do -- error 
    print(char) 
end 

for i = 1, str:len() do 
    print(str[ i ]) -- nil 
end 

回答

101

在Lua 5.1,你可以在幾個方面進行迭代串本的字符

的基本循環是:

 
for i = 1, #str do 
    local c = str:sub(i,i) 
    -- do something with c 
end 

,但它可能是更有效的使用模式與string.gmatch(),並得到了字符的迭代器:

 
for c in str:gmatch"." do 
    -- do something with c 
end 

甚至用string.gsub()呼籲每個字符的功能:

 
str:gsub(".", function(c) 
    -- do something with c 
end) 

在所有我已經利用了string模塊被設置爲所有字符串值的元數據的事實,所以它的函數可以使用:表示法作爲成員調用。我還使用了(新到5.1,IIRC)#來獲取字符串長度。

爲您的應用程序的最佳答案取決於很多因素,和基準是你的朋友,如果表現,都無關緊要。

你可能要評估爲什麼你需要遍歷字符,看那個已經綁定到Lua正則表達式模塊中的一個,或者一個現代的方法看看羅伯託lpeg模塊,實現瞭解析Lua的表達語法。

+0

感謝。關於你提到的lpeg模塊 - 是否在標記之後保存原始文本中的標記位置?我需要執行的任務是通過lua語法突出特定的簡單語言(沒有編譯的C++解析器)。另外,如何安裝lpeg?似乎它在發行版中有.c源代碼 - 是否需要與lua一起編譯? – grigoryvp 2009-05-07 09:25:55

+0

構建lpeg將生成一個DLL(或.so),它應該存儲在需要可以找到它的地方。 (即由lua安裝中全局package.cpath的內容標識的某處)。如果要使用其簡化語法,還需要安裝其伴隨模塊re.lua。從lpeg語法中,您可以通過多種方式獲得回調和捕獲文本,並且可以使用捕獲來簡單地存儲匹配的位置以供以後使用。如果語法高亮是目標,那麼PEG不是一個不錯的工具選擇。 – RBerteig 2009-05-07 21:32:17

10

如果您使用的Lua 5,嘗試:

for i = 1, string.len(str) do 
    print(string.sub(str, i, i)) 
end 
4

根據手邊的任務,使用string.byte可能會更容易。這也是最快的方法,因爲它避免了創建新的子字符串,這在Lua中變得非常昂貴,這要歸功於每個新字符串的散列並檢查它是否已知。您可以使用相同的string.byte預先計算符號代碼以保持可讀性和可移植性。

local str = "ab/cd/ef" 
local target = string.byte("/") 
for idx = 1, #str do 
    if str:byte(idx) == target then 
     print("Target found at:", idx) 
    end 
end 
-1

所有的人都認爲不太最佳方法

的日子:

function chars(str) 
     strc = {} 
     for i = 1, #str do 
      table.insert(strc, string.sub(str, i, i)) 
     end 
     return strc 
    end 

    str = "Hello world!" 
    char = chars(str) 
    print("Char 2: "..char[2]) -- prints the char 'e' 
    print("-------------------\n") 
    for i = 1, #str do -- testing printing all the chars 
     if (char[i] == " ") then 
      print("Char "..i..": [[space]]") 
     else 
      print("Char "..i..": "..char[i]) 
     end 
    end