我正在尝试优化PHP
正则表达式,并正在寻求精彩Stack Overflow社区的指导。
我试图在HTML
块中捕获预定义的匹配项,例如:
##test##
##!test2##
##test3|id=5##
将运行的示例文本是:
Lorem ipsum dolor sit amet,## test ## consectetur adipiscing elit。 Pellentesque id congue massa。 Curabitur ## test3 | id = 5 ## egestas ullamcorper sollicitudin。 Mauris venenatis sed metus vitae pharetra。
到目前为止我有两种选择。从优化的角度来看最好的想法是什么?
选项1
~##(!?)(test|test2|test3)(|\S+?)##~s
选项2
~\##(\S+)##~s
对于示例"!"
中的\##!test2##
,它旨在标记项目在处理时的特殊行为。这可以移动为##test3|force=true&id=5##
之类的属性。如果是这种情况,那就是:
选项3
~##(test|test2|test3)(|\S+?)##~s
我们关注的最重要因素是性能和优化。
提前感谢您的帮助和见解!
答案 0 :(得分:2)
正如其他人所提到的,你需要为表达式计时。 Python
具有精彩的timeit
模块,而对于PHP
,您需要提出自己的解决方案:
<?php
$string = <<<DATA
Lorem ipsum dolor sit amet, ##test## consectetur adipiscing elit. Pellentesque id congue massa. Curabitur ##test3|id=5## egestas ullamcorper sollicitudin. Mauris venenatis sed metus vitae pharetra.
DATA;
function timeit($regex, $string, $number) {
$start = microtime(true);
for($i=0;$i<$number;$i++) {
preg_match_all($regex, $string, $matches);
}
return microtime(true) - $start;
}
$expressions = ['~##(!?)(test|test2|test3)(|\S+?)##~s', '~\##(\S+)##~s', '~##(test|test2|test3)(|\S+?)##~s'];
$cnt = 1;
foreach ($expressions as $expression) {
echo "Expression " . $cnt . " took " . timeit($expression, $string, 10**5) . "\n";
$cnt++;
}
?>
<小时/> 在我的计算机上运行(每次迭代100k)会产生
Expression 1 took 0.45759010314941
Expression 2 took 0.34269499778748
Expression 3 took 0.40994691848755
显然,您可以使用其他字符串和更多迭代,但这会给您一个大致的想法。
答案 1 :(得分:0)
如果您需要根据字符出现来剖析和处理匹配的子字符串,那么在正则表达式步骤中分离组件似乎最合乎逻辑 - 在准确性和易于处理之后关注模式优化。
我的模式包含三个捕获组,只有中间一个需要一个正长度的字符串。否定捕获组用于模式效率。我假设您的子字符串不包含用于分隔子字符串的#
。如果它们可能包含#
,那么请更新您的问题,我会更新我的答案。
模式说明:
/ // pattern delimiter
## // match leading substring delimiter
(!)? // optionally capture: an exclamation mark
([^#|]+) // greedily capture: one or more non-hash, non-pipe characters
\|? // optionally match: a pipe
([^#]+)? // optionally capture: one or more non-hash characters
## // match trailing substring delimiter
/ // pattern delimiter
代码:(Demo)
$string='Lorem ipsum dolor sit amet, ##test## consectetur adipiscing elit. Pellentesque id congue massa. Curabitur ##test3|id=5## egestas ullamcorper sollicitudin. Mauris venenatis sed metus ##!test2## vitae pharetra.';
$result=preg_replace_callback(
'/##(!)?([^#|]+)\|?([^#]+)?##/',
function($m){
echo '$m = ';
var_export($m);
echo "\n";
// execute custom processing:
if(isset($m[1][0])){ //check first character of element (element will always be set because $m[2] will always be set)
echo "exclamation found\n";
}
// $m[2] is required (will always be set)
if(isset($m[3])){ // will only be set if there is a positive-length string in it
echo "post-pipe substring found\n";
}
echo "\n---\n";
return '[some replacement text]';
},$string);
var_export($result);
输出:
$m = array (
0 => '##test##',
1 => '',
2 => 'test',
)
---
$m = array (
0 => '##test3|id=5##',
1 => '',
2 => 'test3',
3 => 'id=5',
)
post-pipe substring found
---
$m = array (
0 => '##!test2##',
1 => '!',
2 => 'test2',
)
exclamation found
---
'Lorem ipsum dolor sit amet, [some replacement text] consectetur adipiscing elit. Pellentesque id congue massa. Curabitur [some replacement text] egestas ullamcorper sollicitudin. Mauris venenatis sed metus [some replacement text] vitae pharetra.'
如果您正在执行自定义替换过程,此方法将“优化”您的字符串处理。