使 RegEx 分组以将行拆分为列

Make RegEx groups to split line into columns

我在创建一些基于逗号的正则表达式时遇到了问题。在下面的结构中,前 19 列应该只用逗号分隔,接下来的 3 列有 { } 但在这些括号内我可以有更多的括号(它是 "script block")。所以对于最后 3 个,我想把所有东西都放在 ,{}

里面

这是结构

ID,AegisName,Name,Type,Buy,Sell,Weight,ATK[:MATK],DEF,Range,Slots,Job,Class,Gender,Loc,wLV,eLV[:maxLevel],Refineable,View,{ Script },{ OnEquip_Script },{ OnUnequip_Script }

以此为例

1624,Lich_Bone_Wand,Lich's Bone Wand,5,20,,800,60:170,,1,2,0x00018314,18,2,2,3,70,1,10,{ bonus bInt,1; bonus bDex,1; bonus bAtkEle,Ele_Undead; .@r = getrefine(); bonus3 bAutoSpellWhenHit,"NPC_WIDECURSE",5,10+.@r; if(.@r>=9){ bonus bMatkRate,3; bonus bMaxSP,300; } },{},{}

我找到了 ([^\,]*),"x(19)."(\{.*\}),"x(2)."(\{.*\}),但它是用 Perl 编写的,我无法翻译成 JavaScript。我可以看到,如果我将 (\{.*\}) 组合三次(像这样 (\{.*\}),(\{.*\}),(\{.*\}),它会得到最后 3 列,而这个 ([^\,]*), 会得到第一列正确拆分但也会干扰最后一个,所以我尝试 "limiting" 它到前 19 次出现,但如果我这样做 ([^\,]*),{19} 它不会工作

我该如何完成?

有不止一种方法可以使用替换和拆分的组合来完成此操作:

  1. 暂时替换{...}中的逗号,按逗号拆分,恢复每个数组项中的逗号
  2. 以逗号分隔,然后组合从第一次出现的 { 到最后一次出现的 } 的数组项,跟踪嵌套
  3. 使用负前瞻进行拆分以避免在 {...}
  4. 中以逗号拆分

这是第一个选项的示例,我们暂时将 {...} 中的逗号替换为:

function properSplit(line) {
    return line
    .replace(/(\{[^,]*,.*?\})(?=,)/g, function(m, p1) {
        return p1.replace(/,/g, '\x01');
    })
    .split(/,/)
    .map(function(item) {
        return item.replace(/\x01/g, ',');
    });
}

var str = "1624,Lich_Bone_Wand,Lich's Bone Wand,5,20,,800,60:170,,1,2,0x00018314,18,2,2,3,70,1,10,{ bonus bInt,1; bonus bDex,1; bonus bAtkEle,Ele_Undead; .@r = getrefine(); bonus3 bAutoSpellWhenHit,\"NPC_WIDECURSE\",5,10+.@r; if(.@r>=9){ bonus bMatkRate,3; bonus bMaxSP,300; } },{},{}";
console.log(JSON.stringify(properSplit(str), null, ' '));

输出:

[
 "1624",
 "Lich_Bone_Wand",
 "Lich's Bone Wand",
 "5",
 "20",
 "",
 "800",
 "60:170",
 "",
 "1",
 "2",
 "0x00018314",
 "18",
 "2",
 "2",
 "3",
 "70",
 "1",
 "10",
 "{ bonus bInt,1; bonus bDex,1; bonus bAtkEle,Ele_Undead; .@r = getrefine(); bonus3 bAutoSpellWhenHit,\"NPC_WIDECURSE\",5,10+.@r; if(.@r>=9){ bonus bMatkRate,3; bonus bMaxSP,300; } }",
 "{}",
 "{}"
]

解释:

  • 第一个 replace(){...} 中的逗号替换为不可打印的字符 '\x01'。它非贪婪地扫描到下一个 }, 模式,其中 , 是一个积极的先行
  • split() 现在缺少 {...}
  • 中的逗号
  • map() 将不可打印的字符恢复为逗号