我尝试解析维基百科的文章。我使用* page-articles.xml文件,他们以wikicode格式备份所有文章。为了去除格式并获取原始文本,我尝试使用正则表达式,但我不是很习惯它。我使用C#作为编程语言。 我尝试使用正则表达式的设计师Expresso,但我的智慧结束了。这就是我想要实现的目标:
该文本可包含以下结构: [[TextN]]或 [[Text1 | TextN]]或 [[文本1 |文本2 | ... | TextN]]
[[....]]模式可以出现在Texti中。我想用TextN替换这些结构
为了识别文本中的结构,我尝试了以下RegEx:
\[\[ ( .* \|?)* \]\]
Expresso似乎与这个一起运行并且无休止地循环。在5分钟后找到相对较小的文本,我取消了测试运行。
然后我尝试了更简单的东西,我想在括号之间捕捉任何东西:
\[\[ .* \]\]
但是当我有一条像:
这样的行[[Word1]] text inbetween [[Word2]]
表达式返回整行,而不是
[[字1]]
[[字2]]
Regex-Experts的任何提示都可以解决这个问题吗?
提前致谢, 弗兰克
答案 0 :(得分:5)
我不会使用正则表达式(因为它们不能很好地处理递归/嵌套)。
相反,我会用手解析文本 *,这在这种情况下并不是特别困难。
您可以将文字表示为元素的流,而每个元素都是
标记可能包含多个元素流,由|
分隔。
elementStream ::= element*
element ::= chunk | tag
chunk ::= TEXT
tag ::= "[[" elementStream otherStreams "]]"
otherStreams ::= "|" elementStream otherStreams
您的解析器可以使用方法表示每个定义。因此,只要有可用文本且接下来的两个字符不是“]]”或“|”,您就会有elementStream
方法调用element
(如果你在标签内)。
每次调用element
都会返回解析的元素,无论是块还是标记。等
这基本上是一个递归下降解析器。 维基百科:http://en.wikipedia.org/wiki/Recursive_descent_parser(不幸的是,文章很长/很复杂)
答案 1 :(得分:3)
\[\[(.*?\]\]
会这样做。
关键是。*?这意味着获得任何角色,但尽可能少。
修改
对于嵌套标签,一种方法是:
\[\[(?<text>(?>\[\[(?<Level>)|\]\](?<-Level>)|(?! \[\[ | \]\] ).)+(?(Level)(?!)))\]\]
这样可以确保[[和]]在整个文本中匹配。
答案 2 :(得分:1)
这是因为正则表达式尝试始终找到可能的最长匹配。您应该更改.*
尝试使用
\[\[([A-Za-z][A-Za-z\d+]*)(\|\1)*\]\]
这只匹配字母,|
符号和双括号中的数字+它会检查值是否以字母开头。
答案 3 :(得分:0)
如果Expresso没有为您服务,您可能需要尝试RegexBuddy。
虽然不是免费的,但它确实提供了一个出色的实时测试环境,您可以在其中查看正则表达式如何与示例文本的一部分匹配。
答案 4 :(得分:0)
如果GPL2不是您的问题,也许您可以查看Screwturn Wiki的源代码,看看专家是如何做到的。它在C#,BTW