我一直在尝试以与wiki标签类似的方式捕获代码块:
{{code:
code goes here
}}
示例代码如下所示,
$strings = array('AbCd1zyZ9', 'foo!#$bar');
foreach ($strings as $testcase) {
if (ctype_alnum($testcase)) {
echo "It is The string $testcase consists of all letters or digits.\n";
} else {
echo "The string $testcase does not consist of all letters or digits.\n";
}
}
基本上我想捕捉{{..}}
之间的任何东西。 HTML页面中嵌入了多个这样的块。
我将不胜感激。
答案 0 :(得分:5)
首先,正则表达式不是解决此问题的好方法。正确的方法是编写一个理解语言语义的解析器,并梳理出细微之处。话虽如此,如果你仍然需要快速而肮脏的基于正则表达式的方法,它将在99.99%的时间内工作但有几个已确认的错误(请参阅答案结束),请点击此处:
您可以使用preg_match_all()
。这是一个概念证明:
$input = "
<html>
<head>
<title>{{code:echo 'Hello World';}}</title>
</head>
<body>
<h1>{{code:\$strings = array('AbCd1zyZ9', 'foo!#$bar');
foreach (\$strings as \$testcase) {
if (ctype_alnum(\$testcase)) {
echo \"It is The string \$testcase consists of all letters or digits.\\n\";
} else {
echo \"The string $testcase does not consist of all letters or digits.\\n\";
}
}
}}</h1>
</body>
</html>
";
$matches = array();
preg_match_all('/{{code:([^\x00]*?)}}/', $input, $matches);
print_r($matches[1]);
输出以下内容:
Array
(
[0] => echo 'Hello World';
[1] => $strings = array('AbCd1zyZ9', 'foo!#');
foreach ($strings as $testcase) {
if (ctype_alnum($testcase)) {
echo "It is The string $testcase consists of all letters or digits.\n";
} else {
echo "The string does not consist of all letters or digits.\n";
}
}
)
小心点。有一些边缘案例错误涉及在“代码”块中遇到}}
提前终止:
}}
出现在带引号的字符串中,则正则表达式过早匹配}
是“代码”区块的最后一个字符,并且紧跟}}
,则会丢失代码块中的结束}
。答案 1 :(得分:2)
正如我在评论中所说,Asaph's answer是一个很好的可靠正则表达式,但在代码块中包含}}
时会崩溃。希望这不会是一个问题,但是因为它有可能,所以最好让你的正则表达式更加广泛。如果我们可以假设在两个单引号之间出现的任何}}
都不表示代码的结尾,就像在Asaph的<div>{{code:$myvar = '}}';}}</div>
示例中那样,我们可以扩展我的正则表达式:
{{code:((?:[^']*?'[^']*?')*?[^']*?)}}
[^']*?'
查找一组非'
字符,后跟单引号,[^']*?'[^']*?'
连续查找其中两个字符。像“{1}}这样”吞下“字符串。我们lazily查找任意数量的这些字符串,然后查找包含'}}'
的任何非字符串代码的其余部分,最后查找结尾[^']*?
。
这使我们可以匹配整个字符串}}
,而不仅仅是{{code:$myvar = '}}';}}
。
然而,这种方法仍然存在问题。在字符串中转义引号(例如在{{code:$myvar = '}}
中)将无法正常工作,因为我们将首先“吞下”{{code:$myvar = '\'}}\'';}}
,然后立即以'\'
结束。也可以确定这些转义的单引号,或者添加对双引号字符串的支持,但是你需要问自己在什么时候使用代码解析器更好。
查看整个正则表达式here。 (如果最初没有匹配任何内容,只需单击窗口即可。)
我如何使用结果来说出位置 它在新的
中}}
使用替换功能:
<div>
preg_replace($expression, "<div>$0</div>", $input)
会插入整个匹配项,并将其放在新的$0
块之间。或者,如果您只想要实际的源代码,请使用<div>
,因为我们在单独的捕获组中捕获了源代码。
再次,请参阅替换here。
我在兔子洞深处走了......
$1
这不会破坏转义的单引号,并且正确匹配{{code:((?:(?:[^']|\\')*?(?<!\\)'(?:[^']|\\')*?(?<!\\)')*?(?:[^']|\\')*?)}}
。
答案 2 :(得分:0)
使用
preg_match_all("/{{(.)*}}/", $text, $match)
其中text
是可能包含代码的文本
这会捕获{{ }}