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

如何用正则表达式从NodeJS函数调用中提取参数?

在Node.js中提取函数调用参数:正则表达式方案可行吗?

问题需求

需要从Node.js的函数调用字符串中提取参数,示例如下:

`foo0()` => [""]
`foo1(1)` => ["1"]
`foo2(1, "HelloThere")` => ["1", "\"HelloThere\""]
`foo3(foo1(1), foo2(foo1(1), 2), 3)` => ["foo1(1)", "foo2(foo1(1), 2)", "3"]
`foo4(
 // 123456
 foo1(1),
 abcdef,
 foo2(1, 2) + foo3(1+2, 333, "Hello"),
 "\nRandom,((,,,Dummy )),, ,, ,String\n"
)` => ["// 123456\n foo1(1)", "abcdef", "foo2(1, 2) + foo3(1+2, 333, \"Hello\")", "\"\nRandom,((,,,Dummy )),, ,, ,String\n\"\n"]

现有尝试

最初尝试用简单逗号分割,但无法处理嵌套括号场景:

> `foo2(1, "HelloThere")`.split(/\s?,\s/g)
Array [ "foo2(1", '"HelloThere")' ]

即使先剥离函数名和外层括号,面对嵌套结构依然失效:

> `foo3(foo1(1), foo2(foo1(1), 2), 3)`
Array(4) [ "foo3(foo1(1)", "foo2(foo1(1)", "2)", "3)" ]

之后实现了字符遍历解析器,能正确处理括号、引号的平衡,满足需求:

// t 是剥离了外层函数名和括号后的输入字符串
let 
    p0 = 0, p1 = 0, i = 0;
    pts = 0,    // 括号计数
    brs = 0,    // 方括号计数
    qt0 = 0,    // 反引号引号状态
    qt1 = 0,    // 单引号状态
    qt2 = 0     // 双引号状态
;
for (const c of t) {
    switch (c) {
    case "(": if (!qt0 && !qt1 && !qt2) { pts++; } break;
    case ")": if (!qt0 && !qt1 && !qt2) { pts--; } break;
    case "[": if (!qt0 && !qt1 && !qt2) { brs++; } break;
    case "]": if (!qt0 && !qt1 && !qt2) { brs--; } break;
    case "`": qt0 = !qt0; break;
    case "'": qt1 = !qt1; break;
    case "\"": qt2 = !qt2; break;
    case ",":
        if (!pts && !brs && !qt0 && !qt1 && !qt2) {
            // t.slice(p0, p1) 即为单个参数,可在此处理
            p0 = ++p1;
            continue;
        }
    }
    p1++;
}
// 处理最后一个参数
const args = [...args, t.slice(p0, p1)];

但希望知道是否可以通过正则表达式直接匹配未被括号、引号包裹的逗号,从而分割参数。

正则表达式解决方案

在ES2018及以上版本(Node.js 10+支持),可以利用正则的递归匹配和正向断言实现需求。核心思路是:匹配逗号时,确保它不在引号内,且当前括号/方括号处于平衡状态。

步骤1:提取函数调用的参数部分

先从完整函数调用字符串中剥离外层函数名和括号:

const funcCall = 'foo3(foo1(1), foo2(foo1(1), 2), 3)';
const paramsStr = funcCall.match(/^\w+\(([\s\S]*)\)$/)?.[1] || '';

步骤2:用正则分割参数

使用递归正则表达式分割参数:

const splitRegex = /,(?=(?:(?:[^`'"\(\)\[\]]|`[^`]*`|'[^']*'|"[^"]*"|\((?R)\)|\[(?R)\]))*$)/;

使用示例

const paramsStr = `
 // 123456
 foo1(1),
 abcdef,
 foo2(1, 2) + foo3(1+2, 333, "Hello"),
 "\nRandom,((,,,Dummy )),, ,, ,String\n"
`;

const args = paramsStr.split(splitRegex).map(arg => arg.trimStart());
// 处理空参数场景(如foo0())
const finalArgs = paramsStr.trim() === '' ? [''] : args;

console.log(finalArgs);
// 输出:["// 123456\n foo1(1)", "abcdef", "foo2(1, 2) + foo3(1+2, 333, \"Hello\")", "\"\nRandom,((,,,Dummy )),, ,, ,String\n\""]

正则说明

  • ,(?=...):匹配逗号,且后面内容满足正向断言条件
  • (?:[^'"()[]]|[^]*|'[^']*'|"[^"]*"|\((?R)\)|\[(?R)\])*:匹配任意字符,要么是非引号/括号的普通字符,要么是成对的引号,要么是成对的括号/方括号(通过(?R)递归匹配内部内容)
  • $:确保断言覆盖到字符串结尾,保证逗号不在任何未闭合的引号或括号内

注意事项

  1. 正则方案依赖ES2018递归匹配特性,Node.js版本需在10及以上
  2. 极端复杂的嵌套场景(多层嵌套括号+转义引号)下,正则的可读性和维护性不如手动解析器
  3. 处理空参数(如foo0())时,需单独判断参数字符串是否为空,返回[""]

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 05:49:57