Php 正则表达式递归地用括号换行
我想用括号把表达式括起来。表达式以一些数学数字开头,以单位结尾,例如:Php 正则表达式递归地用括号换行,php,regex,preg-replace,Php,Regex,Preg Replace,我想用括号把表达式括起来。表达式以一些数学数字开头,以单位结尾,例如: 4+(5+6)*3 meter (23+4)*3*(76+5) second 我想要的结果是: (4+(5+6)*3) meter ((23+4)*3*(76+5)) second 问题是递归调用该函数,并且仅当preg\u replace之后字符串中没有变化时才会停止,因此以下尝试: preg_replace('/(.+)(?=\s+[a-z]+$)/', '($1)', '4+(5+6)*3 meter') 永远不
4+(5+6)*3 meter
(23+4)*3*(76+5) second
我想要的结果是:
(4+(5+6)*3) meter
((23+4)*3*(76+5)) second
问题是递归调用该函数,并且仅当preg\u replace
之后字符串中没有变化时才会停止,因此以下尝试:
preg_replace('/(.+)(?=\s+[a-z]+$)/', '($1)', '4+(5+6)*3 meter')
永远不会停止,结果将是:
(4+(5+6)*3) meter
((4+(5+6)*3)) meter
(((4+(5+6)*3))) meter
etc..
我想知道是否只有在数学部分还没有用括号括起来的情况下,才有办法进行替换。表达式的第二个示例将使解决方案更加困难。您需要确保第一个捕获组添加了不在括号内的约束:
preg_replace('/^([^(].+?[^)])(?=\s+[a-z]+$)/', '($1)', '4+(5+6)*3 meter')
编辑:
如@Talvir所述,这在以下情况下不起作用:
(1+2)*(3+4)
因为这意味着我们需要用堆栈机器跟踪开括号和闭括号(而正则表达式无法做到这一点),所以我认为没有正则表达式的解决方案。我在下班后尝试了这一点,我认为这会奏效。我在这里的想法是通过删除匹配的括号重复减少表达式,直到没有剩余的括号为止。如果最终表达式是非空的,那么我们需要用括号将原始表达式括起来,否则我们就不需要了 例如,如果表达式是
((1+2)*(2+1))+1
,则缩减如下:
((1+2)*(2+1))+1)
代码如下:
$input = $output = '(23+4)*3*(76+5) meter';
// Split into arithmetic expression and the unit string bit
if (preg_match('/^(.+?)\s*([a-z]+)$/', $input, $match)) {
$exp = $match[1];
$unit = $match[2];
// This is the main logic
// Reduce the expression by repetitively removing closet matching parenthesis
$reduced_exp = $exp;
do {
// The fifth parameter $count returns the number replacements done
$reduced_exp = preg_replace('/\([^()]+\)/', '', $reduced_exp, -1, $count);
} while ($count); // Exit the loop if there are zero replacements
// If reduced expression is non-empty then we need to wrap it with the parenthesis
if (!empty($reduced_exp)) {
$output = '('.$exp.') '.$unit;
}
}
print_r($output); // Outputs ((23+4)*3*(76+5))
/^([^\(].+?[^\])(?=\s+[a-z]+$)/
@Deadooshka,你的答案是有效的,但你不必在character类中转义括号。@Deadooshka它对我的第二个示例不起作用这对(1+2)*(3+4)
这样的表达式不起作用。很好!我试过一些表达方式,它们都很有效。谢谢