4

我有以下形式的字符串:

cake!apple!

apple!

cake!juice!apple!cake!

juice!cake!

换言之,这些字符串由三个子字符串"cake!""apple!"组成"juice!"

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

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

但是 Lua 的模式没有|操作符,所以貌似不能这样。

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

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

我知道要编写代码来做到这一点,但我想不出一个捷径来做到这一点。我正在寻找一个简短的解决方案。我想知道是否有一个我不知道的优雅解决方案。有任何想法吗?

4

7 回答 7

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
于 2013-11-13T14:34:11.133 回答
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"为一个空字符串,正确的匹配最终将是一个空字符串。

它有缺陷(有时不可能找到字符串中从未出现过的字符),但我认为它适用于许多情况。

于 2013-11-13T14:11:18.520 回答
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 匹配总是锚定的。

于 2013-11-14T02:06:42.227 回答
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
于 2013-11-13T14:22:59.510 回答
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

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

于 2013-11-13T14:24:36.640 回答
0

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

于 2013-11-13T14:03:55.650 回答
-3

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

str="juice!"

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

此致

于 2013-11-13T14:01:26.903 回答