尝试使用REGEX过滤多个值的字符串

时间:2016-10-16 09:55:49

标签: javascript regex

我需要根据结构化的源字符串匹配多个行的多个组。

字符串的格式为每行一个名称,但是还有一些其他值,按此顺序:

  • 在每行开始名称前可以有一个数字;
  • 可能在数字和名称之间有一些垃圾分隔符;
  • 名称可以包含任何字符,包括括号,撇号等符号;
  • 在名称后面有3或4个字母的括号之间可能有代码(不要担心名称在括号之间有3或4个字母的可能性,这不会发生)
  • 在分行前的行尾可能有一个星号。

我需要为每一行检索这4组。这就是我正在尝试的:

/^(\d+)?(?:[ \t]?[x:.=]?)[ \t]?(.+?)(?=[ \t]?(\(\w{3,4}\))?[ \t]?(\*))$/igm

要记住这个数字:

^(\d+)?

清理可能的分隔符:

(?:[ \t]?[x:.=]?)

过滤每组之间的空间:

[ \t]?

名称(以及其他名称):

(.+?(?=[ \t]?(\(\w{3,4}\))?[ \t]?(\*)?))

显然,问题在于最后一个问题。它一起捕捉(第2,3和4组)。正如您所看到的,我尝试将最后两个可选组作为积极前瞻,将它们与名称分开。

我做错了什么或者如何更好地实现结果呢?

修改

字符串示例:

2 John Smith
3 Messala Oliveira (NMN) *
Mary Pop *
Joshua Junior (pMHH)

我需要什么:

[ "2", "John Smith", "", "" ],
[ "3", "Messala Oliveira", "(NMN)", "*" ],
[ "", "Mary Pop", "", "*" ],
[ "", "Joshua Junior", "(pMHH)", "" ],

1 个答案:

答案 0 :(得分:0)

您需要使用可选的非捕获组包装可能存在或不存在的捕获组:

/^(?:(\d+)[ \t]*)?(.*?)(?:[ \t](\(\w{3,4}\)))?(?:[ \t](\*))?$/igm

请参阅regex demo

<强>详情:

  • ^ - 字符串开头
  • (?:(\d+)[ \t]*)? - 可选的非捕获组匹配
    • (\d+) - (第1组)1+位数
    • [ \t]* - 0 +空格或制表符(如果使用\s,则为0 +空格)
  • (.*?) - 第2组尽可能少地捕获除了亚麻布符号以外的任何0 +字符
  • (?:[ \t](\(\w{3,4}\)))? - 可选的组匹配
    • [ \t] - 空格或标签
    • (\(\w{3,4}\)) - 第3组捕获(,3或4个字的字符,)
  • (?:[ \t](\*))? - 与空格或制表符匹配的另一个可选组,并将*符号捕获到第4组。
  • $ - 字符串结束。

如果您单独测试字符串,[ \t]可以替换为更简单的\s

&#13;
&#13;
var regex = /^(?:(\d+)\s*)?(.*?)(?:\s(\(\w{3,4}\)))?(?:\s(\*))?$/i;
var strs = ['2 John Smith','3 Messala Oliveira (NMN) *','Mary Pop *','Joshua Junior (pMHH)'];

for (var i=0; i<strs.length; i++) {
    if ((m = regex.exec(strs[i])) !== null) {
        var res = [];
        if (m[1]) { 
          res.push(m[1]); 
        } else res.push("");
        res.push(m[2]);
        if (m[3]) { 
          res.push(m[3]); 
        } else res.push("");
        if (m[4]) { 
          res.push(m[4]); 
        } else res.push("");
    }
    console.log(res);
}
&#13;
&#13;
&#13;