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

寻求匹配并移除未闭合括号的PHP正则表达式解决方案

移除PHP字符串中未闭合的括号

问题分析

你之前使用的正则\((?:[^)(]*(?R)?)*+\)只能匹配完全闭合的嵌套圆括号,既无法处理方括号[],也无法定位并移除未闭合的孤立括号,因此达不到预期效果。要同时处理()和[]的未闭合场景,采用栈遍历的方法逻辑更清晰、结果更可靠。

栈实现方案

通过栈跟踪括号的嵌套状态,准确标记有效闭合的括号,移除未匹配的孤立括号:

function removeUnclosedBrackets(string $str): string {
    $bracketPairs = ['(' => ')', '[' => ']'];
    $reversePairs = array_flip($bracketPairs);
    $stack = [];
    $keep = array_fill(0, strlen($str), true);

    foreach (str_split($str) as $index => $char) {
        // 遇到左括号,入栈记录位置与类型
        if (isset($bracketPairs[$char])) {
            $stack[] = ['index' => $index, 'type' => $char];
        } 
        // 遇到右括号,匹配栈顶的左括号
        elseif (isset($reversePairs[$char])) {
            $matched = false;
            // 从栈顶往前找匹配的左括号,清理不匹配的左括号
            for ($i = count($stack) - 1; $i >= 0; $i--) {
                if ($stack[$i]['type'] === $reversePairs[$char]) {
                    array_splice($stack, $i, 1);
                    $matched = true;
                    break;
                } else {
                    $keep[$stack[$i]['index']] = false;
                    array_splice($stack, $i, 1);
                }
            }
            // 无匹配左括号,标记当前右括号为移除项
            if (!$matched) {
                $keep[$index] = false;
            }
        }
    }

    // 栈中剩余的左括号均为未闭合项,标记移除
    foreach ($stack as $item) {
        $keep[$item['index']] = false;
    }

    // 过滤移除项,生成结果
    $result = '';
    foreach (str_split($str) as $index => $char) {
        if ($keep[$index]) {
            $result .= $char;
        }
    }

    return $result;
}

// 测试示例
$test1 = "A Pro Webcam ((Good text) [[Good Text] more texts";
$test2 = "Text (Example (Good text) [Good Text] more texts";

echo removeUnclosedBrackets($test1) . PHP_EOL;
// 输出: A Pro Webcam (Good text) [Good Text] more texts

echo removeUnclosedBrackets($test2) . PHP_EOL;
// 输出: Text Example (Good text) [Good Text] more texts

正则辅助方案(适合无交叉嵌套场景)

如果你的字符串不存在([)]这类交叉嵌套的括号,也可以用递归正则先保留闭合结构,再移除孤立括号:

function removeUnclosedBracketsRegex(string $str): string {
    $parenCache = [];
    // 处理圆括号
    while (preg_match('/\((?:[^()]|(?R))*\)/', $str)) {
        $str = preg_replace_callback('/\((?:[^()]|(?R))*\)/', function($match) use (&$parenCache) {
            static $counter = 0;
            $key = "{PAREN_$counter}";
            $parenCache[$key] = $match[0];
            $counter++;
            return $key;
        }, $str);
    }
    $str = preg_replace('/[()]/', '', $str);
    foreach ($parenCache as $key => $value) {
        $str = str_replace($key, $value, $str);
    }

    // 处理方括号
    $parenCache = [];
    while (preg_match('/\[(?:[^[\]]|(?R))*\]/', $str)) {
        $str = preg_replace_callback('/\[(?:[^[\]]|(?R))*\]/', function($match) use (&$parenCache) {
            static $counter = 0;
            $key = "{BRACKET_$counter}";
            $parenCache[$key] = $match[0];
            $counter++;
            return $key;
        }, $str);
    }
    $str = preg_replace('/[\[\]]/', '', $str);
    foreach ($parenCache as $key => $value) {
        $str = str_replace($key, $value, $str);
    }

    return $str;
}

注意:正则方案无法处理交叉嵌套的括号,栈方案则可以正确处理所有嵌套情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 12:01:02