正则表达式:重复捕获没有全局标记的组

时间:2014-05-09 14:54:03

标签: javascript regex

我试图在文本中识别和处理音乐和弦符号。在这样做的过程中,我最终尝试匹配一组重复模式,但只返回最后匹配的实例。

"Amaj13#11".match(/([a-g][#|b]?)(?:(maj|m|sus|dim|#|b)?(\d+))*/i)

// Expected
["Amaj13#11", "A", "maj", "13", "#", "11"]

// Actual
["Amaj13#11", "A", "#", "11"]

应该捕获其他字词的群组是:(?:(maj|m|sus|dim|#|b)?(\d+))*

据我了解,这是因为没有全局标志不存在,当我添加它时,它正确地提取并匹配正确的部分并返回字符串"Amaj13#11",这使我回到正方形。< / p>

如何使用全局标志并将返回的组件放在数组中,或者在没有它的情况下重复捕获组?

一些示例输入和所需输出。

"C#m9#5" // ["C#", "m", "9", "#", "5"]
"Bsus2" // ["B", "sus", "2"]
"Db#11" // ["Db", "#", "11"]
"Fmaj6b2" // ["F", "maj", "6", "b", "2"]

1 个答案:

答案 0 :(得分:3)

这是一个有趣的问题,因为虽然它似乎挑战javascript,但它有一个简单的答案。

我建议的方法是忘记捕获组并尝试拆分。但Javascript没有lookbehinds(在指定拆分分隔符时很有用),据我所知它没有选项来拆分字符串并保留分隔符,就像PHP一样。这导致我们采用两步法。

第一步:决定我们要分割的位置。从你所说的,听起来我们正在看一个像

这样的简单正则表达式

[A-Gb#]|(?:maj|sus)|\d+

请根据您的需要进行修改。

第二步:在分割点插入标记。为此,我们使用replace:

readyToSplit = str.replace(/([A-Gb#]|(?:maj|sus)|\d+)/mg, "$1[SPLIT]");

这给了我们:

A[SPLIT]maj[SPLIT]13[SPLIT]#[SPLIT]11[SPLIT]

第三步:拆分。

result = readyToSplit.split(/\[SPLIT\]/m);

这为我们提供了:Amaj13#11

您可能需要调整令牌,但这是一般想法。