正则表达式:捕获组可能不存在。我该怎么写呢?

时间:2016-11-09 20:11:58

标签: regex

以下是我需要解析的字符串的一些示例:

1 - Cream Soda (0.99)
5 - Potato Chips (2.50)
12 - Atlantic Salmon

我想捕获第一个数字,产品名称和价格,包括括号。有时价格和相关的括号不存在。

我想出了这个正则表达式:

/(\d+)\s+-\s*(.+)\s+(\(.*\))/

仅在所有三个组都存在时才有效。我也试过这个:

/(\d+)\s+-\s*(.+)\s+(\(.*\))?/

但它没有更好。

如何使第三个捕获组可选?

如果它有任何不同,这是在javascript中。

2 个答案:

答案 0 :(得分:1)

您可以使用可选的非捕获组包裹尾随部分,并且模式需要用锚点包装:

/^(\d+)\s+-\s*(.*?)(?:\s+(\([^()]+\)))?$/

请参阅regex demo

<强>详情:

  • ^ - 字符串开头
  • (\d+) - 第1组捕获前1个或多个数字
  • \s+ - 一个或多个空格
  • - - 连字符
  • \s* - 0+ whitespaces
  • (.*?) - 第2组捕捉任何0+字符,但尽可能少
  • (?:\s+(\([^()]+\)))? - 匹配1或0个序列的可选组:
    • \s+ - 1+空格
    • (\([^()]+\)) - 第3组捕获(,除()以外的1个字符,然后)
  • $ - 字符串结束。

var strs = ["1 - Cream Soda (0.99)", "5 - Potato Chips (2.50)", "12 - Atlantic Salmon"];
var re = /^(\d+)\s+-\s*(.*?)(?:\s+(\([^()]+\)))?$/;
for (var s of strs) {
  var m = re.exec(s);
  if (m) {
    console.log("1: " + m[1] + ", 2: " + m[2] + (m[3] ? ", 3: " + m[3] : ""));
  }
}

答案 1 :(得分:1)

你可以让第二组懒惰并在第三组中使用line end作为替代匹配:

(\d+)\s+-\s*(.+?)\s*(\(.*\)|$)

RegEx Demo