正则表达式,用于验证具有多个字母数字模式的字符串

时间:2019-06-03 13:33:56

标签: javascript regex regex-lookarounds regex-group regex-greedy

我正在制造一个机器人,我希望该机器人能够跟踪团体费用。我需要能够告诉漫游器所支付的金额和参与者(即,输入输入内容的用户所支付的人员列表)。参与者必须是从大写拉丁字母中提取的两个字母的序列(不允许使用数字或其他符号)。

示例:假设我要与朋友FH,GT,YU,WQ和CS一起吃午餐。为了一起告诉机器人有关我们的午餐,我将输入支付的总金额,然后输入“ |”,然后输入除我以外的其他参加活动的相关人员(例如FH,GT,YU,WQ, CS)。 如果需要(虽然不是必需的话),我还可以在名称列表后放置一个空格并写下事件的名称:如果存在,则事件的名称必须始终用双引号(“)引起来。

例如,这是有效的输入:

 65|FH,GT,YU,WQ,CS "lunch out"

因此,格式为:数字,|,名称(用逗号分隔),空格,事件的名称。 (最后两个是可选的。)

该数字必须始终为正(出于显而易见的原因),并且可以是整数(例如65)或十进制(例如65.7、65.32等)。如果数字是十进制数字,则小数点后最多可以有两位数字。

所有这些都是有效的输入:

65|FH,GT,YU,WQ,CS 
34.56|FH,GT "club night"
120.7|FH,GT,KM,LW,AS,XZ,PO "cinema tickets"

同一参与者不能被多次提及,因此以下输入无效。

65|FH,GT,YU,WQ,CS,GT

简而言之:该命令应以金额开头,后跟分隔符|,然后是用户付款的人员列表。插入描述费用的消息是可选的。

有许多有效的输入。它们都是不同的,但是它们都将遵循上述规则(两次都没有提及参与者,每个参与者用逗号分隔,金额是整数或小数,小数点后最多2位,依此类推。 )。

但是,我似乎无法“捕获”它们共同共享的内容(它们的“格式”遵循我所陈述的规则),以便机器人可以区分有效输入和无效输入。我当时正在考虑使用正则表达式。我对正则表达式不是很熟悉,但是在我看来,正则表达式无法捕获输入可能具有的所有可能形式(例如,名称数,数量中的小数位数,事件等等)

我应该如何进行?

2 个答案:

答案 0 :(得分:1)

也许可以使用正则表达式来处理重复项,但是为了简化起见,我将使用split并循环

var txt = `65|FH,GT,YU,WQ,CS
34.56|FH,GT "club night"
65|FH,GT,YU,WQ,CS,GT "this is not valid"
65|AH,GT,YU,AH
120.7|FH,GT,KM,LW,AS,XZ,PO "cinema tickets"`

var lines = {
  valid: [],
  notValid: []
};

txt.split("\n").forEach(line => {
  var isValid = true,
    persons = [],
    l = line.trim().replace(/.*\|([\w,]+)(\s".*)?/, "$1")

  l.split(/[,\s]/).forEach(p => {
    if (persons.includes(p))
      isValid = false;
    persons.push(p)
  })

  if (isValid)
    lines.valid.push(line)
  else
    lines.notValid.push(line)
})

console.log(lines)

答案 1 :(得分:0)

这个表达很有趣。我们将使用现有的模式来解决这个问题,该模式包括数字和管道:

(\d+(\.\d+)?)\|

不想要的重复两个字母:

(([A-Z]{2}),?).*?(\1)

所需的重复两个字母:

(([A-Z]{2}),?)

引号中的可选字词:

\s+"[\w\s]+"

我们可以使用更改:

(\d+(\.\d+)?)\||(([A-Z]{2}),?).*?(\1)|(([A-Z]{2}),?)|\s+"[\w\s]+"

只要第二部分不是undefined,则该字符串无效,否则有效,我们将编写其余问题的脚本。

Demo

测试

const regex = /(\d+(\.\d+)?)\||(([A-Z]{2}),?).*?(\1)|(([A-Z]{2}),?)|\s+"[\w\s]+"/gm;
const str = `65|FH,GT,YU,WQ,CS 
34.56|FH,GT "club night"
120.7|FH,GT,KM,LW,AS,XZ,PO "cinema tickets"

65|FH,GT,YU,WQ,CS,GT`;
let m;

while ((m = regex.exec(str)) !== null) {
    // This is necessary to avoid infinite loops with zero-width matches
    if (m.index === regex.lastIndex) {
        regex.lastIndex++;
    }
    
    // The result can be accessed through the `m`-variable.
    m.forEach((match, groupIndex) => {
        console.log(`Found match, group ${groupIndex}: ${match}`);
    });
}

RegEx电路

jex.im可视化正则表达式:

enter image description here