Scala regexps:如何将匹配作为数组或列表返回

Dfr*_*Dfr 14 regex scala

有没有一种简单的方法可以将regex匹配作为数组返回?
以下是我的尝试方式2.7.7:

val s = """6 1 2"""
val re = """(\d+)\s(\d+)\s(\d+)""".r
for (m <- re.findAllIn (s)) println (m) // prints "6 1 2"
re.findAllIn (s).toList.length // 3? No! It returns 1!
Run Code Online (Sandbox Code Playgroud)

但我接着尝试了:

s match {
  case re (m1, m2, m3) => println (m1)
}
Run Code Online (Sandbox Code Playgroud)

这很好用!m1为6,m2为1等.

然后我发现了一些让我感到困惑的事情:

val mit = re.findAllIn (s)
println (mit.toString)
println (mit.length)
println (mit.toString)
Run Code Online (Sandbox Code Playgroud)

打印:

non-empty iterator
1
empty iterator
Run Code Online (Sandbox Code Playgroud)

"length"调用以某种方式修改迭代器的状态.这里发生了什么?

Dan*_*ral 27

好的,首先,了解findAllIn返回一个Iterator.An Iterator是一次消耗可变对象.你做的任何事都会改变它.如果您不熟悉迭代器,请阅读它们.如果您希望它可重用,则将findAllIn的结果转换为a List,并仅使用该列表.

现在,您似乎想要所有匹配的,而不是所有匹配.该方法findAllIn将返回可在字符串上找到的完整正则表达式的所有匹配项.例如:

scala> val s = """6 1 2, 4 1 3"""
s: java.lang.String = 6 1 2, 4 1 3

scala> val re = """(\d+)\s(\d+)\s(\d+)""".r
re: scala.util.matching.Regex = (\d+)\s(\d+)\s(\d+)

scala> for(m <- re.findAllIn(s)) println(m)
6 1 2
4 1 3
Run Code Online (Sandbox Code Playgroud)

看到有两个匹配,并且它们都不包括字符串中间的",",因为那不是任何匹配的一部分.

如果你想要这些组,你可以这样得到它们:

scala> val s = """6 1 2"""
s: java.lang.String = 6 1 2

scala> re.findFirstMatchIn(s)
res4: Option[scala.util.matching.Regex.Match] = Some(6 1 2)

scala> res4.get.subgroups
res5: List[String] = List(6, 1, 2)
Run Code Online (Sandbox Code Playgroud)

或者,使用findAllIn,像这样:

scala> val s = """6 1 2"""
s: java.lang.String = 6 1 2

scala> for(m <- re.findAllIn(s).matchData; e <- m.subgroups) println(e)
6
1
2
Run Code Online (Sandbox Code Playgroud)

matchData方法将Iterator返回Match而不是String.


Rex*_*err 9

unapplySeq如何解释多个组与findAllIn的工作方式有所不同.findAllIn在字符串上扫描您的模式并返回匹配的每个字符串(如果成功则通过匹配前进,或者如果失败则返回一个字符).

所以,例如:

scala> val s = "gecko 6 1 2 3 4 5"
scala> re.findAllIn(s).toList
res3: List[String] = List(6 1 2, 3 4 5)
Run Code Online (Sandbox Code Playgroud)

另一方面,unapplySeq假定与序列完美匹配.

scala> re.unapplySeq(s)
res4: Option[List[String]] = None
Run Code Online (Sandbox Code Playgroud)

因此,如果要分析在精确正则表达式字符串中指定的组,请使用unapplySeq.如果要查找看起来像正则表达式模式的字符串子集,请使用findAllIn.如果你想两者兼顾,请自行链接:

scala> re.findAllIn(s).flatMap(text => re.unapplySeq(text).elements )
res5: List[List[String]] = List(List(6, 1, 2), List(3, 4, 5))
Run Code Online (Sandbox Code Playgroud)