当我们在Lua中没有`|`运算符时如何验证这个字符串?

时间:2013-11-13 13:49:15

标签: string lua lua-patterns

我有以下形式的字符串:

cake!apple!

apple!

cake!juice!apple!cake!

juice!cake!

换句话说,这些字符串由三个子字符串"cake!""apple!""juice!"组成。

我需要验证这些字符串。因此,使用正则表达式执行此操作的方法是:

/^(apple!|juice!|cake!)*$/

但是Lua的模式没有|运算符,因此它似乎无法以这种方式完成。

如何在Lua中验证我的字符串?

(我不关心字符串的内容:我只关心它们是否符合(验证)。)

我知道要编写代码来执行此操作,但我想不出一个简短的方法来执行此操作。我正在寻找一个简短的解决方案。我想知道是否有一个我不知道的优雅解决方案。有什么想法吗?

7 个答案:

答案 0 :(得分:5)

if str:gsub("%w+!", {["apple!"]="", ["juice!"]="", ["cake!"]=""}) == "" then
    --do something
end

此解决方案使用表作为string.gsub的第二个参数。由于模式都匹配%w+,表格将第二次验证,只有真正的三个模式被替换为空字符串。如果在完成替换后,字符串变为空,则匹配成功。

使用辅助表变量可以使其更清晰:

local t = {["apple!"]="", ["juice!"]="", ["cake!"]=""}
if str:gsub("%w+!", t) == "" then
    --do something
end

答案 1 :(得分:2)

例如,如果字符中永远不会出现字符,则普通字符串中的字符"\1"(ASCII 1)不太可能,您可以使用:

local str = "cake!juice!apple!cake!"
if str:gsub("apple!","\1"):gsub("juice!","\1"):gsub("cake!","\1"):gsub("\1","") == "" then
    --do something
end

通过将模式的每个匹配替换为"\1",最后将"\1"替换为空字符串,正确的匹配最后将是一个空字符串。

它有缺陷(有时候找不到字符串中的字符是不可能的),但我认为它适用于很多情况。

答案 2 :(得分:1)

以下似乎适用于(包括的)快速测试。

local strs = {
    "cake!apple!",
    "bad",
    "apple!",
    "apple!bad",
    " apple!bad",
    "cake!juice!apple!cake!",
    "cake!juice! apple!cake!",
    "cake!juice!badapple!cake!",
    "juice!cake!",
    "badjuice!cake!",
}

local legalwords = {
    ["cake!"] = true,
    ["apple!"] = true,
    ["juice!"] = true,
}

local function str_valid(str)
    local newpos = 1
    for pos, m in str:gmatch("()([^!]+!)") do
        if not legalwords[m] then
            return
        end
        newpos = pos + m:len()
    end
    if newpos ~= (str:len() + 1) then
        return nil
    end

    return true
end

for _, str in ipairs(strs) do
    if str_valid(str) then
        print("Match: "..str)
    else
        print("Did not match: "..str)
    end
end

答案 3 :(得分:1)

只是提供另一个答案,您可以使用lpeg的re模块轻松完成此操作:

re = require 're'

local testdata =
{
  "cake!apple!",
  "apple!",
  "cake!juice!apple!cake!",
  "cake!juice!badbeef!apple!cake!",
  "juice!cake!",
  "badfood",
}

for _, each in ipairs(testdata) do
  print(re.match(each, "('cake!' / 'apple!' / 'juice!')*") == #each + 1)
end

输出:

true
true
true
false
true
false

这看起来几乎就像你上面的正则表达式减去^ $当然因为lpeg匹配总是被锚定。

答案 4 :(得分:0)

Lua模式不是正则表达式的替代,也不能代表这种模式。在这种情况下,你只需要反复确保字符串的前面与你的一个单词匹配,然后将其弹出,但你可能已经知道了。

答案 5 :(得分:0)

类似的东西:

local words = {cake=1,apple=2,juice=3}
local totals = {}
local matches = 0
local invalid = 0
string.gsub("cake!","(%a+)!",
   function(word)
      local index = words[word]
      if index then
         matches = matches + 1
         totals[index] = totals[index] + 1
      else
         invalid = invalid + 1
      end
   end
)

if matches > 0 and invalid == 0 then
   -- Do stuff
end

这会将每个单词传递给提供的函数,您可以在其中验证每个单词。

答案 6 :(得分:-3)

我不知道它是否会帮助你解决问题。但是使用string.find()我可以使用“”。看:

str="juice!"

print(string.find(str, "cake!" or "teste"))

最好的问候