Lua模式匹配 -- 如何使它工作?

我有一个要处理的文本文件,其示例内容如下所示:

> > [FCT-FCTVALUEXXXX-IA] > 名称=值 > 标签=值 > 零个或多个文本行 > 缩写= > 零个或多个文本行 > 字段A=1 > 字段B=0 > 零个或多个文本行 > 隐藏=N > [Text-FCT-FCTVALUEXXXX-IA-Note] > 一个或多个注释行 > [FCT-FCT-FCTVALUEZ-IE-DETAIL] > 零个或多个文本行 > [FCT-FCT-FCTVALUEQ-IA-DETAIL] > 零个或多个文本行 > [FCT-_FCTVALUEY-IA] > 名称=值 > 零个或多个文本行 > 标签=值 > 零个或多个文本行 > 字段A=1 > 缩写=值 > 字段A=1 > 零个或多个文本行 > 隐藏=N > >

我需要查找类似于这样的部分:

> > [FCT-FCTVALUEXXXX-IA] > 名称=值 > 标签=值 > 零个或多个文本行 > 缩写= > 零个或多个文本行 > 字段A=1 > 字段B=0 > 零个或多个文本行 > 隐藏=N > >

并提取FCT-FCTVALUEXXXX-AA、名称、标签、缩写、字段A和B以及隐藏,并找到相应的部分(如果存在):

> > [Text-FCT-FCTVALUEXXXX-IA-Note] > 一个或多个注释行 > >

最后将注释行提取为单个字符串。

我不关心这些部分

> > [FCT-FCT-FCTVALUEZ-IE-DETAIL] > 零个或多个文本行 > >

这三种不同的部分可以出现在文件中的任何位置,包括在末尾,并且这些部分之间的位置没有可预测的关系。

缩写、字段A和B的顺序不能保证,但它们始终出现在名称和标签之后以及隐藏之前。

到目前为止,我只做到了这些:

strParse = "(%[FCT%-.-%-)([IF])([EA])%]%c+名称=(.-)%c.-标签=(.-)%c(.-)隐藏=(%a)%c" --不能同时将所有字段都提取出来,因为某些字段的顺序是不可预测的
for id, rt, ft, name, label, detail, hidden in strFacts:gmatch(strParse) do
    --提取详细信息
    缩写=detail:match("缩写=(.-)%c") --可能为空
    if 缩写 == nil then 缩写 = "" end
    字段A = detail:match("字段A=(%d)")
    字段B = detail:match("字段B=(%d)")
    --需要对可能附加了一堆无关材料的标识符进行清理,并使用它来获取注释
    ident=id:match(".*(%[FCT%-.-%-$)")..rt..ft
    注释 = ParseAutonote(ident)  --这是一个解析注意事项的函数,我还没有测试,所以一个虚拟函数返回""
    tblResults[name]={ident, rt, ft, name, label, 缩写, 字段A, 字段B, hidden, 注释}
end

大部分都可以工作正常(经过数小时的工作),但是没有工作的部分是:

(".*(%[FCT%-.-%-$)")

它应该从字符串id中提取FCT-sometext-的最后一次出现

我的逻辑:将搜索锚定到字符串结尾,并捕获以"\[FCT-"开头,以"-"结尾的最短可能字符串,位于字符串结尾处。

给定一个值为"\[FCT-\_ABCD-PDQR-"或 "\[FCT-XYZ-DETAIL]lines of text\[FCT-\_ABCD-PDQR-"当我希望它返回"FCT-\_ABCD-PDQR-"时,它会返回nil。 (请注意,ABCD、PDQR等可以是任何包含Alpha、-和\_的长度为任意文本)。

点赞
用户7396148
用户7396148

正如您自己发现的那样,(".*(%[FCT%-.-%-)$") 的工作方式正是您想要的,而 (".*(%[FCT%-.-%-$)") 不行。 $^ 是锚点,必须出现在模式的末尾或开头,不能出现在捕获闭包内。

当锚点字符出现在模式的任何其他位置时,它们将成为您要查找的字符串的一部分,除非在集合中使用 ^ 来排除字符,即:排除大写字母 [^A-Z]

以下是使用示例字符串和您提出的模式进行模式匹配的示例。

print(string.match("[FCT-_ABCD-PDQR-", (".*(%[FCT%-.-%-$)")))  -- 初始模式
> nil
print(string.match("[FCT-_ABCD-PDQR-$", (".*(%[FCT%-.-%-$)"))) -- 在字符串末尾添加 $
> [FCT-_ABCD-PDQR-$
print(string.match("[FCT-_ABCD-PDQR-", (".*(%[FCT%-.-%-)$")))  -- 将 $ 移动到模式末尾
> [FCT-_ABCD-PDQR-
2018-12-27 17:08:00