gpt4 book ai didi

javascript - 用于匹配 MediaWiki 模板及其参数的正则表达式

转载 作者:搜寻专家 更新时间:2023-11-01 05:26:01 25 4
gpt4 key购买 nike

我正在编写一个简单的 Javascript,以将特定参数添加到当前正在编辑的文章中的特定模板。

维基百科模板的结构如下:

 {{Template name|unnamed parameter|named parameter=some value|another parameter=[[target article|article name]]|parameter={{another template|another tamplate's parameter}}}}

一个模板也可以覆盖多行,例如:

{{Template 
|name=John
|surname=Smith
|pob=[[London|London, UK]]
}}

如需进一步引用,请查看 http://en.wikipedia.org/wiki/Help:Template

所以首先我想匹配整个模板。我过来了部分解决方案,即:

document.editform.wpTextbox1.value.match(/\{\{template name((.|\n)*?)\}\}$/gmis)

但是问题是它只匹配从初始括号到第一个嵌套模板(第一个示例)的右括号的文本。

另外我想以数组形式获取它的参数。因此,对于结果,我想获得一个包含特定顺序参数的数组。 Array( 参数 pob 的值,参数 name 的值,参数 surname 的值,参数 pod 的值(在本例中为空,因为它未设置))

我会用它来清理某些文章中的非标准化格式并添加一些新参数。

谢谢!

最佳答案

编写简单的解析器。

用正则表达式解决这类问题是不对的。它与匹配括号相同 - 很难用正则表达式来做。正则表达式一般不适用于嵌套表达式。

尝试这样的事情:

var parts = src.split(/(\{\{|\}\})/);
for (var i in parts) {
if (parts[i] == '{{') // starting new (sub) template
else if (parts[i] == '}}') // ending (sub) template
else // content (or outside)
}

这只是伪代码,因为我现在很着急,将更新此代码以使其正常工作...

更新(2011 年 8 月 9 日)

var NO_TPL = 0, // outside any tpl - ignoring...
IN_TPL = 1, // inside tpl
IN_LIST = 3; // inside list of arguments

function parseWiki(src) {
var tokens = src.split(/(\{\{|\}\}|\||=|\[\[|\]\])/),
i = -1, end = tokens.length - 1,
token, next, state = NO_TPL,
work = [], workChain = [], stateChain = [];

function trim(value) {
return value.replace(/^\s*/, '').replace(/\s*$/, '');
}

// get next non empty token
function getNext(next) {
while (!next && i < end) next = trim(tokens[++i]);
return next;
}

// go into tpl / list of arguments
function goDown(newState, newWork, newWorkKey) {
stateChain.push(state);
workChain.push(work);

if (newWorkKey) {
work[newWorkKey] = newWork;
} else {
work.push(newWork);
}

work = newWork;
state = newState;
}

// jump up from tpl / list of arguments
function goUp() {
work = workChain.pop();
state = stateChain.pop();
}

// state machine
while ((token = getNext())) {
switch(state) {

case IN_TPL:
switch(token) {
case '}}': goUp(); break;
case '|': break;
default:
next = getNext();
if (next != '=') throw "invalid";
next = getNext();
if (next == '[[') {
goDown(IN_LIST, [], token);
} else if (next == '{{') {
goDown(IN_TPL, {id: getNext()}, token);
} else {
work[token] = next;
}
}
break;

case IN_LIST:
switch(token) {
case ']]': goUp(); break;
case '|': break;
default: work.push(token);
}
break;

case NO_TPL:
if (token == '{{') {
next = getNext();
goDown(IN_TPL, {id: next});
}
break;
}
}

return work;
}

单元测试

describe('wikiTpl', function() {
it('should do empty tpl', function() {
expect(parseWiki('{{name}}'))
.toEqual([{id: 'name'}]);
});

it('should ignore text outside from tpl', function() {
expect(parseWiki(' abc {{name}} x y'))
.toEqual([{id: 'name'}]);
});

it('should do simple param', function() {
expect(parseWiki('{{tpl | p1= 2}}'))
.toEqual([{id: 'tpl', p1: '2'}]);
});

it('should do list of arguments', function() {
expect(parseWiki('{{name | a= [[1|two]]}}'))
.toEqual([{id: 'name', a: ['1', 'two']}]);
});

it('should do param after list', function() {
expect(parseWiki('{{name | a= [[1|two|3]] | p2= true}}'))
.toEqual([{id: 'name', a: ['1', 'two', '3'], p2: 'true'}]);
});

it('should do more tpls', function() {
expect(parseWiki('{{first | a= [[1|two|3]] }} odd test {{second | b= 2}}'))
.toEqual([{id: 'first', a: ['1', 'two', '3']}, {id: 'second', b: '2'}]);
});

it('should allow nested tpl', function() {
expect(parseWiki('{{name | a= {{nested | p1= 1}} }}'))
.toEqual([{id: 'name', a: {id: 'nested', p1: '1'}}]);
});
});

注意:我在这些单元测试中使用了 Jasmine 的语法。您可以使用包含整个测试环境的 AngularJS 轻松运行它 - 在 http://angularjs.org 查看它

关于javascript - 用于匹配 MediaWiki 模板及其参数的正则表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6532276/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com