我正在尝试在维基百科模块中使用 Lua 模式匹配来定位 Mediawiki 参数语法的实例(例如
{{{parameter1-a|defaultValue}}}
或 {{{parameter1-a|{{{alias1-a|defaultValue}}}}}}
),以便将它们转换为 Lua 兼容的参数语法。 (是的,我完全知道为此使用模式匹配是不可原谅的危害人类罪,但无论如何。)
到目前为止,我有这个相对简单的模式,在大多数情况下效果很好:
"{{{([^{}<>|]+)(|?([^{}|]*))}}}"
(正则表达式等效 [希望],如果你想在 regex101 上测试:
/{{{([^{}<>|]+)(?:\|([^{}|]+)?)?}}}/g
)
但是,这不能正确匹配本身包含大括号的“默认”部分中的任何内容,因此我不能在默认中包含参数或模板 wiki 文本的别名。更具体地说:
{{{parameter|{{{alias|default}}}}}}
这样的东西,只会匹配/捕获{{{参数|{{{alias
|default
}}}}}}。"{{{([^{}<>|]+)(|?([^{}|]*))}}}"
) 将成功获得 {{{parameter|{{{alias}}}}}}
,按预期产生 {{{parameter
|{{{alias}}}
}}},但在别名上有默认值时它会给出 {{ {参数|{{{alias
|default}}}
}}}"{{{([^{}<>|]+)(|?(.*))}}}"
) 与一个参数完美配合,但如果第一个参数有默认值,则有两个它会“溢出”:{{{parameter1|default}}} {{{parameter2}}}
将产生 {{{parameter1
|default}}} {{{parameter2
}}} 我该如何解决这个问题?
这似乎是 Lua 特殊括号匹配模式项的完美用例
%b
!使用%b{}
,你可以匹配一对匹配的花括号。通过在每一侧用两个花括号包围它,您可以匹配三对花括号。
鉴于您的测试用例:
local text = [[
lorem ipsum dolor sit amet
{{{blarg}}}
lorem ipsum dolor sit amet
{{{blarg|default}}}
lorem ipsum dolor sit amet
{{{parameter1-a|{{{alias1-a|defaultValue}}}}}}
]]
并在
{{%b{}}}
中使用模式gmatch
:
for match in text:gmatch"{{%b{}}}" do
print(match)
end
你得到
{{{blarg}}}
{{{blarg|default}}}
{{{parameter1-a|{{{alias1-a|defaultValue}}}}}}
如预期。然后你可以进一步处理这个参数:
local content = match:sub(4, -4) -- cut off curly braces
local param, default = match:match"^([^|]+)|([^|]+)$"
if not param then param = content end -- no default
(我在这里稍微简化了你的模式,这并不完全等同;它更宽松)