2009-05-06 40 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