Lua 中的正则表达式问题

我有一个URL字符串,需要从匹配中获取某些单词。

例如:

/school/student/studentname1/detail/55/address/address1

我可以像这样传递以获取所需信息的详细信息:

local s1,s2,s3 =myString:match("/school/student/(.-)/detail/(.-)/address/(.-)")

现在问题是,我的字符串可能是

myString = /school/student/studentname1

myString = /school/student/studentname1/detail/55

在这种情况下,我的正则表达式会失败,需要帮助?

点赞
用户8291949
用户8291949

这是我能想到的最好的单行代码:

local s1,s2,s3 =myString:match("/[^/]+/[^/]+/([^/]+)/?[^/]*/?([^/]*)/?[^/]*/?([^/]*)")

演示

解释:

我使用负字符类以通用的方式获取斜杠之间的文本。这使得以 * 作为类和 / 作为斜杠更容易标识后面的部分为可选项(您可以将初始部分 less generic 并且只使用 /school/student/)。

这在 (PC)RE 中很容易,但是 Lua Patterns 不支持可选捕获组以及替换。 相反,您可以使用 rex_pcre 库 中的 PCRE 模式来使用 Lua 或使用模式匹配的库 Lpeg

2018-08-16 06:46:33
用户7500028
用户7500028

首先,您的原始模式未按预期工作,因为它未捕获地址(因为您使用了 .- 这不是贪心的)

因此,修复原始模式的一种方法可以是使用 /school/student/([^/]+)/detail/([^/]+)/address/([^/]+)

其中 [^/] 表示除 / 之外的任何字符

然后,为了选择地匹配一些选项,并且由于 Lua 模式不允许可选组,您可能需要像这样使用多个步骤:

myString = "/school/student/studentname1/detail/55"
local s1,s2,s3
s1 =myString:match("/school/student/([^/]+)")
if (s1 ~= nil) then
  print(s1)
  s2 =myString:match("/detail/([^/]+)")
  if (s2 ~= nil) then
    print(s2)
    s3 =myString:match("/address/([^/]+)")
    if (s3 ~= nil) then
      print(s3)
    end
  end
end

最后,如果您想确保详细信息和地址按照给定的顺序出现,则可以使用此方法:

myString = "/school/student/studentname1/address/myaddress"
local s1,s2,s3
s1 =myString:match("/school/student/([^/]+)")
if (s1 ~= nil) then
  print(s1)
  s1,s2 =myString:match("/school/student/([^/]+)/detail/([^/]+)")
  if (s2 ~= nil) then
    print(s2)
    s1,s2,s3 =myString:match("/school/student/([^/]+)/detail/([^/]+)/address/([^/]+)")
    if (s3 ~= nil) then
      print(s3)
    end
  end
end

这样,它将找到 /school/student/studentname1/detail/55,但不会找到 /school/student/studentname1/address/myaddress。如果您不需要像这样使用它,则仅使用第一版。

2018-08-16 07:21:28
用户6834680
用户6834680
local all_fields = { student = 1, detail = 2, address = 3 }

local function parse(str)
   local info = {}
   local index
   for w in str:gmatch"/([^/]+)" do
      if index then
         info[index] = w
         index = nil
      else
         index = all_fields[w]
      end
   end
   return (table.unpack or unpack)(info, 1, 3)
end

local myString = '/school/student/studentname1/detail/55/address/address1'
local s1, s2, s3 = parse(myString)
print(s1, s2, s3)

myString = '/school/student/studentname1/address/address1'
s1, s2, s3 = parse(myString)
print(s1, s2, s3)

myString = '/school/student/studentname1/detail/55'
s1, s2, s3 = parse(myString)
print(s1, s2, s3)

local all_fields = { student = 1, detail = 2, address = 3 } -- 定义包含所有字段索引的表

local function parse(str) -- 定义解析函数,参数为字符串
   local info = {} -- 定义空表 info
   local index -- 定义变量 index
   for w in str:gmatch"/([^/]+)" do -- 遍历字符串中所有的 "/" 前缀
      if index then -- 如果 index 不为空
         info[index] = w -- 将表 info 中索引为 index 的元素赋值为 w
         index = nil -- index 设为空
      else -- 如果 index 为空,即 w 是一个字段名
         index = all_fields[w] -- 将 index 设为对应的索引值
      end
   end
   return (table.unpack or unpack)(info, 1, 3) -- 返回 info 表中索引为 1、2、3 的前三个元素
end

-- 定义要解析的字符串
local myString = '/school/student/studentname1/detail/55/address/address1'
-- 调用解析函数并将结果赋值给三个变量
local s1, s2, s3 = parse(myString)
-- 打印解析结果
print(s1, s2, s3)

myString = '/school/student/studentname1/address/address1'
s1, s2, s3 = parse(myString)
print(s1, s2, s3)

myString = '/school/student/studentname1/detail/55'
s1, s2, s3 = parse(myString)
print(s1, s2, s3)
2018-08-16 08:01:55