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)
我有一个 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)