正则表达式匹配多个选项

3

我正在尝试匹配类型定义。

def euro : t1 -> t2 -> t3 (and this pattern my repeat further in other examples)

我想出了这个正则表达式。
^def ([^\s]*)\s:\s([^\s]*)(\s->\s[^\s]*)*

尽管它匹配了eurot1,但接下来它

  • -> t2匹配而不是t2
  • 无法匹配任何带有t3的内容

我不知道自己做错了什么,我的目标是捕获

euro t1 t2 t3

作为四个单独的项目,我目前得到的是:
0: "def euro : t1 -> t2 -> t3"
1: "euro"
2: "t1"
3: " -> t3"

正则表达式匹配整个字符串,其中包括子字符串t2和子字符串-> t2?你想要将t2放在自己的捕获组中吗? - CertainPerformance
2个回答

1
你不能在JS的正则表达式中使用 重复捕获组,除了最后一个值,其余都会被"丢弃",并在每个后续迭代中重新编写。

创建一个需要捕获组来抓取匹配文本部分的正则表达式时,常见错误是重复捕获组而不是捕获重复组。不同之处在于,重复的捕获组只会捕获最后一次迭代,而捕获另一个重复组的组将捕获所有迭代。

解决方法可以是捕获整个子字符串,然后拆分它。这里有一个例子:

var s = "def euro : t1 -> t2 -> t3";
var rx = /^def (\S*)\s:\s(\S*)((?:\s->\s\S*)*)/;
var res = [];
var m = s.match(rx);
if (m) {
  res = [m[1], m[2]];
  for (var s of m[3].split(" -> ").filter(Boolean)) {
     res.push(s);
  }
}
console.log(res);

模式细节

  • ^ - 字符串的开头
  • def - 一个字面量子字符串
  • (\S*) - 捕获组1:0个或多个非空格字符
  • \s:\s - 用单个空格括起来的冒号
  • (\S*) - 捕获组2:0个或多个非空格字符
    • ((?:\s->\s\S*)*) - 捕获组3:以下模式序列的0个或多个重复:
    • \s->\s - 空格,->,空格
    • \S* - 0个或多个非空格字符

@SimonH 这是一个非捕获组。它仅用于将模式分组,因此不需要捕获构造开销。 - Wiktor Stribiżew

0

细节:

  • ?: - 创建一个非捕获组
  • $1 - 接收第一个捕获组即\w+的结果
  • \s[\:\-\>]+\s - 匹配" : "" -> "
  • \w+ - 匹配重复的字母数字模式
  • let str = 'def euro : t1 -> t2 -> t3';
    let regex = /(?:def\s|\s[\:\-\>]+\s)(\w+)/g;
    
    let match = str.replace(regex, '$1\n').trim().split('\n');
    console.log(match);


    1
    你不应该使用[\w\d]+,因为\w+可以完成同样的工作。\w匹配ASCII字母、数字或下划线。 - Wiktor Stribiżew

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接