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

我有以下格式的字符串:

cake!apple!

apple!

cake!juice!apple!cake!

juice!cake!

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

我需要验证这些字符串。使用正则表达式进行此操作的方法如下:

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

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

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

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

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

点赞
用户2983034
用户2983034

我不知道它是否能帮助你解决问题。但是我可以用string.find()方法使用“ or ”。看下面的例子:

str="juice!"

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

祝好!

2013-11-13 14:01:26
用户787480
用户787480

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

2013-11-13 14:03:55
用户1009479
用户1009479

如果字符串中永远不会出现某个字符,例如字符 "\1"(ASCII 1)在正常字符串中不太可能出现,你可以使用以下方法:

local str = "cake!juice!apple!cake!"
if str:gsub("apple!","\1"):gsub("juice!","\1"):gsub("cake!","\1"):gsub("\1","") == "" then
    --做某些事情
end

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

它有缺陷(有时不可能找到一个永远不在字符串中的字符),但我认为它在许多情况下都可以使用。

2013-11-13 14:11:18
用户258523
用户258523

以下内容似乎在 (包括的) 快速测试中工作。

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-13 14:22:59
用户2633831
用户2633831
本地变量 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
   -- 进行操作
end

这段代码将每个单词传递给指定函数,在函数中你可以验证每一个单词。

2013-11-13 14:24:36
用户1009479
用户1009479

这个解决方案使用表作为 string.gsub 的第二个参数。由于所有的模式都匹配 %w+,因此表只会验证真正的三个模式,并将其替换为一个空字符串。如果在所有替换之后,字符串变为空,那么匹配成功。

使用一个辅助表变量可以让它更加清晰:

local t = {["apple!"]="", ["juice!"]="", ["cake!"]=""}
if str:gsub("%w+!", t) == "" then
    --do something
end
2013-11-13 14:34:11
用户234175
用户234175

为了提供另一个答案,您可以使用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-14 02:06:42