Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 正则表达式递归地用括号换行_Php_Regex_Preg Replace - Fatal编程技术网

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
  • (*)+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)
    这样的表达式不起作用。很好!我试过一些表达方式,它们都很有效。谢谢