lua 中的正则表达式模式问题

Regex pattern issue in 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

在那种情况下,我的正则表达式失败了,有什么帮助吗?

这是我能想到的最好的一行:

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

Demo

解释:

我使用否定字符 类 以通用方式获取斜线之间的文本。这使得使用 * 表示 类 和 ? 表示斜杠更容易将后面的部分标记为可选(您可以使初始部分不那么通用,只需使用 /school/student/)。

使用 (PC)RE 很容易,但是,Lua 模式不支持 optional capture groups as well as alternations. Instead, you can use PCRE patterns in Lua with the rex_pcre library or use the pattern-matching library Lpeg

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

所以修复原始模式的一种方法是使用 /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。如果你不需要这样,就用第一个版本吧。

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)