我需要匹配{{和}}
之间的所有内容我正在尝试解析维基百科,但是在运行rexex代码之后,我最终得到了orphan}}。这是我的PHP脚本。
<?php
$articleName='england';
$url = "http://en.wikipedia.org/wiki/Special:Export/" . $articleName;
ini_set('user_agent','custom agent'); //required so that Wikipedia allows our request.
$feed = file_get_contents($url);
$xml = new SimpleXmlElement($feed);
$wikicode = $xml->page->revision->text;
$wikicode=str_replace("[[", "", $wikicode);
$wikicode=str_replace("]]", "", $wikicode);
$wikicode=preg_replace('/\{\{([^}]*(?:\}[^}]+)*)\}\}/','',$wikicode);
print($wikicode);
?>
我认为问题是我嵌套{{和}}例如
{{something {{something else {{something new}} {{something old}} something blue}} something green}}
答案 0 :(得分:4)
您可以使用:
\{\{(.*?)\}\}
大多数正则表达式都将大括号{
视为文字字符,除非它是像{x,y}
这样的重复运算符的一部分,而不是这里的情况。所以你不需要用反斜杠来逃避它,尽管这样做会得到相同的结果。
所以你也可以使用:
{{(.*?)}}
样品:
$ echo {{StackOverflow}} | perl -pe 's/{{(.*?)}}/$1/'
StackOverflow
另请注意,此处以非贪婪的方式使用匹配任何字符(除换行符之外)的.*
。所以它会尝试尽可能少地匹配。
示例:
在字符串'{{stack}}{{overflow}}'
中,它将匹配'stack'
而不是'stack}}{{overflow'
。
如果您想要以后的行为,可以将.*?
更改为.*
,使比赛贪婪。
答案 1 :(得分:2)
您的编辑显示您正在尝试进行递归匹配,这与原始问题非常不同。如果您不只是删除匹配的文本,我会建议您不要使用正则表达式,但这应该做你想要的:
$wikicode=preg_replace('~{{(?:(?:(?!{{|}}).)++|(?R))*+}}~s',
'', $wikicode);
在第一个{{
与开始分隔符匹配后,(?:(?!{{|}}).)++
会占用所有内容,直到下一个分隔符为止。如果它是另一个开放分隔符,(?R)
将接管并以递归方式再次应用整个正则表达式。
(?R)
和正则表达式功能一样非标准。它是PCRE库的独特之处,它支持PHP的正则表达式。其他一些风格有自己的匹配递归结构的方式,所有这些都非常不同。
答案 2 :(得分:0)
\{{2}(.*)\}{2}
或更清洁,有外观(?<=\{{2}).*(?=\}{2})
,但前提是您的正则表达式引擎支持它们。
如果您希望匹配在首次找到}}
时停止(即非贪婪),则应将.*
替换为.*?
。
此外,您应该考虑引擎的单行匹配设置,因为其中一些.
默认情况下不会匹配换行符。您可以启用单行,也可以使用[.\r\n]*
代替.*
。
答案 3 :(得分:0)
除了使用已经提到的非贪婪量词之外,您还可以使用:
\{\{(([^}]|}[^}])*)}}
内部([^}]|}[^}])*
仅用于匹配零个或多个不包含序列}}
的任意字符的序列。
答案 4 :(得分:0)
获得最短匹配的贪婪版本是
\{\{([^}]*(?:\}[^}]+)*)\}\}
(为了进行比较,使用字符串{{fd}sdfd}sf}x{dsf}}
,延迟版本\{\{(.*?)\}\}
需要57步才能匹配,而我的版本只需要17步。这假设Regex Buddy的调试输出可以信任。 )