如何在特定子串前分割字符串数组?附trackButtonEvent提取方案
问题
我有一个包含多个trackButtonEvent(子串的长字符串,希望在该子串出现位置之前分割字符串得到数组(默认split方法会丢弃该子串,实际结果和期望不符)。最终目标是提取所有形如trackButtonEvent(...);的子串组成数组,想问除了先分割再提取的方式外,有没有更优的替代方案?
示例代码
const contents: string = "Here is a file that has multiple instances of the trackButtonEvent(...); and here is another one trackButtonEvent(...); and now here is another occurrence trackButtonEvent(...); this is the end of the file."; const contentArray: string[] = contents.split("trackButtonEvent("); console.log("contentArray --> ", contentArray) // 期望结果 ['Here is a file that has multiple instances of the ', 'trackButtonEvent(...); and here is another one ', 'trackButtonEvent(...); and now here is another occurrence ', 'trackButtonEvent(...); this is the end of the file.'] // 实际结果 ['Here is a file that has multiple instances of the ', '...); and here is another one ', '...); and now here is another occurrence ', '...); this is the end of the file.']
现有提取函数
function grabAnalyticStats(contents, nameOfAnalytic, start, end) { const exists = contents.includes(nameOfAnalytic); let itemString = ''; if (exists) { const item = getStringInBetween(contents, start, end); itemString = start + item + end; } return itemString; }
期望最终数组
['trackButtonEvent(...some code #1);', 'trackButtonEvent(...some code #2);', 'trackButtonEvent(...some code #3);']
最优解决方案:正则表达式全局匹配
直接用正则表达式全局匹配所有符合格式的子串,这是最直接高效的方式,不需要先分割再处理。
基础版(无嵌套括号)
如果你的trackButtonEvent(...)括号内没有嵌套的);结构,用这个简单正则即可:
const contents: string = "Here is a file that has multiple instances of the trackButtonEvent(...some code #1); and here is another one trackButtonEvent(...some code #2); and now here is another occurrence trackButtonEvent(...some code #3); this is the end of the file."; // 正则规则:匹配完整的trackButtonEvent(...);结构 const regex = /trackButtonEvent\([^)]*\);/g; const matchedResults = contents.match(regex) || []; console.log(matchedResults); // 输出:['trackButtonEvent(...some code #1);', 'trackButtonEvent(...some code #2);', 'trackButtonEvent(...some code #3);']
正则说明:
trackButtonEvent\(:匹配固定开头,\(转义括号避免被正则解析为分组[^)]*:匹配括号内所有非)的字符,直到遇到第一个)\);:匹配结尾的);g:全局标志,确保匹配所有符合条件的子串
进阶版(支持嵌套括号)
如果括号内存在嵌套的括号结构(比如trackButtonEvent(handleClick());),基础正则会失效,这时可以用支持递归的正则(ES2018及以上版本支持):
const nestedRegex = /trackButtonEvent\((?:[^)(]|\((?:[^)(]|\([^)(]*\))*\))*\);/g; const nestedMatchedResults = contents.match(nestedRegex) || [];
实现「分隔符前分割并保留分隔符」的需求
如果只是想实现split时保留trackButtonEvent(子串,可以用正则的正向预查特性:
const contents: string = "Here is a file that has multiple instances of the trackButtonEvent(...); and here is another one trackButtonEvent(...); and now here is another occurrence trackButtonEvent(...); this is the end of the file."; // 正向预查:在trackButtonEvent(出现的位置前分割,不消耗该子串 const splitResult = contents.split(/(?=trackButtonEvent\()/); console.log(splitResult); // 输出:['Here is a file that has multiple instances of the ', 'trackButtonEvent(...); and here is another one ', 'trackButtonEvent(...); and now here is another occurrence ', 'trackButtonEvent(...); this is the end of the file.']
说明:(?=...)是正向预查,它匹配一个位置,该位置后面紧跟指定字符串,但不会把该字符串作为分割的一部分消耗掉,因此split后会保留trackButtonEvent(子串。
内容的提问来源于stack exchange,提问作者Crystal
相关产品推荐
相关产品推荐

