2.7 字符串的模式查找

问题

你想要在String中搜索,查看其是否包含一个正则表达式。

解决方案

在一个字符串上调用.r方法可以创建一个Regex对象,如果想在一个字符串中查找一个Regex匹配的模式则使用其findFirstIn方法,如果想查找所有匹配的模式则使用其findAllIn方法。

为了验证上面的说法,首先需要为想要搜索的模式创建一个Regex,下面这个例子是查找一个或多个数字字符的序列:

下一步,创建一个用来搜索的字符串样例:

findFirstIn方法将找到第一个匹配结果:

注意,这个方法的返回值是Option[String]。

接下来看看寻找多个匹配时使用的findAllIn方法:

如上所示,findAllIn返回一个迭代器,可以在这个迭代器上循环访问每一个匹配的结果:

如果findAllIn没有找到任何结果,会返回一个空的迭代器,所以仍然可以调用其方法而不会抛出空指针异常。如果想将结果转换成一个Vector,则只要在其后面继续调用toVector即可:

如果没有任何匹配,上面这种方式将产生一个空的Vector。其他方法如toList、toSeq和toArray在没有任何匹配时也是可用的。

讨论

在一个字符串上使用.r方法是创建一个Regex对象的最简单的方法。另一种方法是导入Regex类,创建一个Regex实例,然后以同样的方式使用该实例:

虽然这么做会需要更多的代码,但是也更清晰明显,因为我发现自己很容易忽视掉字符串末尾的.r(然后会花几分钟来搞清楚代码竟然能正常工作的原因)。

关于findFirstIn的返回类型是Option的一些简要讨论

正如前面的解决方案里提到的,findFirstIn方法会找到例子中第一个匹配项然后返回Option[String]:

因为Option/Some/None模式将在24.6节介绍,所以这里不会详细讨论。Option简单来说是一个容纳0个或1个值的容器,在上面findFirstIn的例子里,如果它成功找到一个匹配,就会用Some把字符串"123"包起来,也就是Some("123")。如果在字符串中没有找到任何匹配项,就会返回一个None:

总之,任何时候一个方法(a)被定义为返回Option[String],(b)保证不抛出异常,(c)保证终止(即不进入无限循环),它总是返回Some[String]或None。

另见

·请参阅Scala Regex类文档(https://oreil.ly/rdiBW),了解更多使用正则表达式的方法。

·请参阅24.6节,了解如何处理Option值的细节。