Scala正则表达式命名捕获组

19
scala.util.matching.Regex trait MatchData中,我看到有支持组名的功能,我认为这与(Regex Named Capturing Groups)有关。
但是由于Java直到版本7才支持组名,据我所知(ref),Scala版本2.8.0(Java HotSpot(TM) 64-Bit Server VM,Java 1.6.给了我这个异常:
scala> val pattern = """(?<login>\w+) (?<id>\d+)""".r
java.util.regex.PatternSyntaxException: Look-behind group does not have an obvio
us maximum length near index 11
(?<login>\w+) (?<id>\d+)
           ^
        at java.util.regex.Pattern.error(Pattern.java:1713)
        at java.util.regex.Pattern.group0(Pattern.java:2488)
        at java.util.regex.Pattern.sequence(Pattern.java:1806)
        at java.util.regex.Pattern.expr(Pattern.java:1752)
        at java.util.regex.Pattern.compile(Pattern.java:1460)

那么问题是Scala支持命名捕获组吗?如果支持,是否有任何示例可用?

2个回答

35

很遗憾,Scala的命名分组并不是以相同的方式定义的。它只是原始模式中无名(即仅编号)组的后处理别名。

这里有一个例子:

import scala.util.matching.Regex

object Main {
   def main(args: Array[String]) {
      val pattern = new Regex("""(\w*) (\w*)""", "firstName", "lastName");
      val result = pattern.findFirstMatchIn("James Bond").get;
      println(result.group("lastName") + ", " + result.group("firstName"));
   }
}

这将打印出来(在ideone.com上看到):
Bond, James

Regex的构造函数中,我们提供了第1组、第2组等的别名。然后我们可以用这些名称来引用这些组。这些名称并不是模式本身固有的。

2
谢谢。没有重载的RichString.r。 - oluies
在Scala 2.11和Java7中,这个行为仍然存在吗? - WestCoastProjects
4
它仍然是。现在你还可以使用 val pattern = """(\w*) (\w*)""".r("firstName", "lastName"); - Majki
@Majki 是的,我已经验证了你所说的。这就是生活。 - WestCoastProjects

3
Scala没有自己的正则表达式匹配实现。相反,底层的正则表达式是Java的,因此编写模式的详细信息是在java.util.regex.Pattern中记录的。
在那里,您会发现您正在使用的语法实际上是后向约束的语法,尽管根据文档,<必须后跟=(正后向约束)或(负后向约束)。

2
这是应该在很久以前就被标记为错误的东西。虽然它在应该抛出异常时确实会抛出,但消息应该是“未知的后向查找组”(显然是预期的)或者更好的“未知的组类型”。当然,在JDK 1.7中修复了这个问题,这是添加命名组的副作用。 - Alan Moore
1
从JDK7开始,这个说法不再正确 - 在JDK中支持组名,但在Scala中不支持。 - WestCoastProjects

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