You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何根据BODMAS规则提取特定括号内内容?现有正则仅支持单对括号

提取嵌套数学表达式中最内层第一个闭合括号的内容

嘿,我懂你的痛点——你原来用的非贪婪正则 preg_match('#\((.*?)\)#', $text, $match) 只会匹配从第一个左括号到第一个右括号的内容,在你的例子里会拿到 2+(3+(5-6,完全不是你要的 5-6。问题出在普通正则不会处理嵌套括号的层级,而你需要的是遵循BODMAS规则的最内层(第一个闭合的)括号内容。

下面给你两种实用的解决方案:

方案一:用简单正则精准匹配最内层括号

如果你的场景是标准数学表达式(括号内不会有转义括号或者其他特殊括号),直接用这个正则就能搞定:

$text = '1+(2+(3+(5-6)))+(7-8)';
// 匹配内部不含任何括号的括号对,也就是最内层的第一个
preg_match('#\(([^()]+)\)#', $text, $match);
echo $match[1]; // 输出: 5-6

这个正则的逻辑很直接:找 ( 后面跟着完全没有括号的内容,再跟着 ),这样就精准定位了最内层的第一个闭合括号对。如果表达式里有多个最内层括号,它会优先匹配第一个出现的,正好符合你的需求。

方案二:手动遍历计数(复杂场景更可靠)

要是你需要处理更复杂的情况(比如表达式里有特殊字符,或者担心正则的边界情况),手动遍历字符串计数括号是更稳妥的选择:

$text = '1+(2+(3+(5-6)))+(7-8)';
$openBrackets = 0;
$targetContent = '';
$lastOpenPos = -1;

for ($i = 0; $i < strlen($text); $i++) {
    $char = $text[$i];
    if ($char === '(') {
        $openBrackets++;
        // 记录当前左括号的位置,下一个右括号对应的就是它
        $lastOpenPos = $i;
    } elseif ($char === ')') {
        $openBrackets--;
        // 遇到第一个闭合的括号对时,提取内容并停止遍历
        if ($lastOpenPos !== -1) {
            $targetContent = substr($text, $lastOpenPos + 1, $i - $lastOpenPos - 1);
            break;
        }
    }
}

echo $targetContent; // 输出: 5-6

这个方法的思路是:遍历字符串时,每遇到左括号就计数加一并记录位置,遇到右括号就计数减一。当我们遇到第一个右括号时,对应的就是最近的那个左括号——这正是最内层的括号对,提取中间的内容就搞定了。

为什么原来的正则失效?

你原来的 #\((.*?)\)# 用了非贪婪匹配,它只会按顺序找第一个 ( 和第一个 ),完全不管中间的嵌套层级。在你的例子里,第一个 ) 是 (5-6) 的右括号,但非贪婪匹配会从最外层的 ( 开始匹配,所以拿到的是 2+(3+(5-6,这显然不符合你的需求。

内容的提问来源于stack exchange,提问作者Kevin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 06:25:44