正则表达式帮助需要解析 mediawiki 模板 Javascript

Regexp assistance needed parsing mediawiki template with Javascript

我正在使用 Javascript 处理 Mediawiki 标记。我正在尝试删除某些参数。我无法准确找到要删除的文本,而且只能找到我要删除的文本。

简化下来,模板文本可以是这样的:

{{TemplateX
| a =
Foo bar
Blah blah

Fizbin foo[[domain:blah]]

Ipsum lorem[[domain:blah]]
|b =1
|c = 0fillertext
|d = 1alphabet
| e =
| f = 10: One Hobbit
| g = aaaa, bbbb, cccc, dddd
|h = 15000
|i = -15000
| j = Level 4 [[domain:filk|Songs]]
| k =7 fizbin, 8 [[domain:trekkies|Shatners]]
|l = 
|m = 
}}

到目前为止我想到的最好的是

/\|\s?(a|b|d|f|j|k|m)([^][^\n\|])+/gm

更新版本:

/\|\s?(a|b|d|f|j|k|m)(?:[^\n\|]|[.\n])+/gm

给出(更新后的正则表达式):

{{TemplateX


|c = 0fillertext

| e =

| g = aaaa, bbbb, cccc, dddd
|h = 15000
|i = -15000

|Songs]]

|Shatners]]
|l = 

但我想得到的是:

{{TemplateX
|c = 0fillertext
| e =
| g = aaaa, bbbb, cccc, dddd
|h = 15000
|i = -15000
|l = 
}}

我可以处理多余的换行符,但我仍然需要确保“|Songs]]”和“|Shatners]]”也与正则表达式匹配。

关于下面 Tgr 的评论,

为了我的目的,可以安全地假设每个参数都在一个新行开始,其中 |是该行的第一个字符,并且没有参数定义包含 |那不在 [[foo|bar]] 结构中。所以 '\n|'是安全的 "start" 和 "stop" 序列。所以问题归结为,对于任何给定的参数(问题中的 a、b、d、f、j、k 和 m),我需要一个匹配以下 'wanted param' 的正则表达式:

| [other param 1] = ... 
| [wanted param] = possibly multiple lines and |s that aren't after a newline
| [other param 2]

您可以在下面尝试这个 - 它匹配您想要包含的变量,而不是那些您想要排除的变量:

(^{{TemplateX)|\|\s*(c|e|g|h|i|l[ ]*\=[ ]*)(.*)|(}}$)

Tested here.

编辑

我增强了它,我认为如果你使用图表工具比较两个正则表达式会更好 regexper.com:

(^{{TemplateX)|(\|[ ]*)(c|e|g|h|i|l)([ ]*\=[ ]*)(.*)|(}}$)

编辑 2

根据评论,匹配不需要的参数的正则表达式是这样的:

\|[ ]?(a|b|d|f|j|k|m)([ ]*\=[ ]*)((?![\r\n]+\|)[0-9a-zA-Z, \[\]:\|\r\n\t])+

利用此 answer - 它使用否定前瞻来仅匹配 [\r\n]+\| 这将部分满足以下声明:

So '\n|' is a safe "start" and "stop" sequence

Tested here 在要保留的参数中引入了一些换行符(例如 g)。

视觉解释:

您的参数值可能包含

以外的字符
[0-9a-zA-Z, \[\]:\|\r\n\t]

要解决这个问题,您需要更新该列表。

试图解释模板语言的全部灵活性是没有希望的。例如,模板可能看起来像

{{TemplateX
| a=1 | b=2 }}

{{TemplateX|
| a=1 <nowiki>|</nowiki> b=2 }}

完全不同(第一个有两个参数,ab,第二个只有一个a参数)。正则表达式(大部分)是上下文无关的,无法理解这样的结构。

所以除非你确定模板总是按照相同的约定使用,否则你最好使用一些合适的解析器,例如 mwparserfromhell:

import mwparserfromhell
wikicode = mwparserfromhell.parse(text)
for template in wikicode.filter_templates(recursive=True, matches=lambda t: t.name.strip() == 'TemplateX'):
for param in ['a', 'b', 'd', 'f', 'j', 'k', 'm']:
    template.remove(param)
print(wikicode)

(这需要在 Python 中重写代码或调用 Python 后端服务。我认为 Javascript 中没有任何好的 wikitext 解析器。)

或者,您可以将 parse APIprop=parsetree 一起使用以获得模板及其参数的 XML 树表示,这并不难处理。