模式与Lua的字符串模块匹配

时间:2009-07-17 01:16:30

标签: string lua find design-patterns

我正在尝试在Lua中使用string.find来解析用户输入的字符串的内容。我试图找到最多三个不同的参数(如果用户输入它们),但有时只有一个。

更长形式的输入字符串如下所示:

local userInput = "x|y|z"

其中xyz可以是任何字符,也可以不是任何字符(空字符串,即"")和 z也可以包含竖条/管道 - 我只想根据遇到的前两个竖条("|")将字符串分成三个部分。困难在于用户也无法使用该表单 - 他或她只能输入"x""x||z""||z"等。在这种情况下,我仍然需要获取值xyz,并且应该清楚它们分配给哪些变量。

例如,我试过这个:

local _,_,a,b,c = string.find(usermsg, "([^|]*)|?([^|]*)|?(.+)")

首先请注意,这甚至无法正确提取abc。但更重要的是,当usermsg只是"x"时,它会将x的值设置为变量c,而它应该是a。当用户输入"x|y"时,变量ax(正确),但变量cy(错误,应将其分配给变量{{} 1}})。

然后我尝试单独进行:

local _,_,a = string.find(usermsg , "([^|]+)|?[^|]*|?.*")
local _,_,b= string.find(usermsg , "[^|]*|([^|]+)|?.*")
local _,_,c= string.find(usermsg , "[^|]*|[^|]*|(.+)")

但这也失败了。它与b匹配,但不与x匹配,y最终为c加上管道和y

任何帮助将不胜感激。谢谢! :)

3 个答案:

答案 0 :(得分:1)

似乎您只是寻找具有最大分割数的典型分割函数。这是我的:

function string.split( str, delim, max, special )
    if max == nil then max = -1 end
    if delim == nil then delim = " " end
    if special == nil then special = False end
    local last, start, stop = 1
    local result = {}
    while max ~= 0 do
        start, stop = str:find(delim, last, not special )
        if start == nil then
            -- if max > #(all ocurances of delim in str), we end here      
            break
        end
        table.insert( result, str:sub( last, start-1 ) )
        last = stop+1
        max = max - 1
    end
    -- add the rest
    table.insert( result, str:sub( last ) )
    return result
end

print( ("A='%s' B='%s' C='%s'"):format(unpack( ("hello|there|world"):split('|', 2) )))
print( ("A='%s' B='%s' C='%s'"):format(unpack( ("||world"):split('|', 2) )))
print( ("A='%s' B='%s' C='%s'"):format(unpack( ("hello||world"):split('|', 2) )))
print( ("A='%s' B='%s' C='%s'"):format(unpack( ("hello|there|"):split('|', 2) )))
print( ("A='%s' B='%s' C='%s'"):format(unpack( ("hello||world|and|the|rest"):split('|', 2) )))

=>

A='hello' B='there' C='world'
A='' B='' C='world'
A='hello' B='' C='world'
A='hello' B='there' C=''
A='hello' B='' C='world|and|the|rest'

答案 1 :(得分:0)

这应该按照您的意图使用

local _,_,a,b = string.find(usermsg, "([^|]*)|?(.*)")
local _,_,b,c = string.find(b, "([^|]*)|?(.*)")

答案 2 :(得分:0)

我认为此问题的最佳解决方案是string.match

local a, b, c = string.match( "(^|*)|(^|*)|(.*)" )

^|匹配任何非|的内容,*表示匹配0或更多。