如何使用可选的微秒模式匹配提取日期时间



我需要想出一个模式来匹配YYYY-MM-DDTHH:MM:SS.s+Z,其中毫秒部分是可选的。正则表达式很简单,看起来像这样:

^d{4}-d{2}-d{2}Td{2}:d{2}:d{2}(.d+)?Z$

匹配以下字符串:

"2022-04-02T11:24:59Z"
"2022-04-02T11:24:59.123Z"
在Lua中,这并不像我想象的那么简单。我尝试了几个模式,但最终只得到了这个工作:
local pat3 = "^%d%d%d%d%-%d%d%-%d%dT%d%d:%d%d:%d%d[%.%d+]*Z$"
local dt1 = "2022-04-02T11:24:59Z"
local dt2 = "2022-04-02T11:24:59.123Z"
local dt_invalid = "2022-04-02T11:24:59.123.000.000Z"
print(dt1:match(pat3))
print(dt2:match(pat3))
print(dt_invalid:match(pat3))

这个模式满足了我的大部分需求,但是像dt_invalid这样的字符串也匹配让我很困扰。我还尝试了以下模式,但没有成功:

local pat1 = "^%d%d%d%d%-%d%d%-%d%dT%d%d:%d%d:%d%d[%.%d+]?Z$"
local pat2 = "^%d%d%d%d%-%d%d%-%d%dT%d%d:%d%d:%d%d(%.%d+)?Z$"

Lua具有简化的模式匹配功能,但是这些模式看起来更像正则表达式模式。我对Lua不够了解,不知道两者的区别,也不知道我遗漏了什么。为什么pat1pat2不工作?有比pat3更好的模式吗?

我强烈建议打开一个Lua独立和训练自己。
对我来说一个非常好的工具是string.gsub(),每个字符串都有所有字符串函数附加为方法。
让事情变得容易多了…

> _VERSION
Lua 5.4
> ("2022-04-02T11:24:59.123Z"):gsub('^%d+%-%d+%-%d+%u%d+%:%d+%:%d+%.%d+%u$', 'MATCH ALL')
MATCH ALL   1
> ("2022-04-02T11:24:59.123Z"):gsub('^%d+%-%d+%-%d+%u%d+%:%d+%:%d+%.%d+%u$', 'Replaced with MATCH: %1')
Replaced with MATCH: 2022-04-02T11:24:59.123Z    1
> -- Lets replace "T" with a space
> ("2022-04-02T11:24:59.123Z"):gsub('T', ' ')
2022-04-02 11:24:59.123Z    1
> -- Cut off the last part
> ("2022-04-02T11:24:59.123Z"):gsub('%.%d+%u$', '')
2022-04-02T11:24:59     1
> -- Finally
> do local date, count = ("2022-04-02T11:24:59.123Z"):gsub('T', ' '):gsub('%.%d+%u$', '') print(date) end
2022-04-02 11:24:59
> -- Lets do a gsub() chain for all three cases
> do local date, count = ("2022-04-02T11:24:59.123Z 2022-04-02T11:24:59Z 2022-04-02T11:24:59.123.000.000Z"):gsub('T', ' '):gsub('%.%d+',''):gsub('%u', '') print(date) end
2022-04-02 11:24:59 2022-04-02 11:24:59 2022-04-02 11:24:59

这里的问题是,为了使一组字符"可量化"(符合将量词分配给集合的条件),则需要将集合的元素括在括号之间。

pat1的情况下,最后一个%d没有被括在括号中,因此+被认为是一个字符而不是一个量词。另一方面,在pat2的情况下,根本不考虑量词。

此外,在LUA中,您不能嵌套集合,因此您不能指定像[%.[%d]+]?这样的模式,因为它只匹配内部量词,而?将被视为正常字符。

我的解决方案是使用一个可能限制较少(可能倾向于匹配其他字符串)的变通方法,仍然可以捕获您需要的部分时间:

%d%d%d%d%-%d%d%-%d%dT%d%d:%d%d:%d%d[%.]?[%d]*Z

漏洞(不应该匹配的行-但匹配的行):

  • "2022 - 04 - 02 - t11:24:59.z"
  • "2022 - 04 - 02 - t11:24:59123z"

这对你的整个字符串集合的情况有帮助吗?

最新更新