![Scala编程实战(原书第2版)](https://wfqqreader-1252317822.image.myqcloud.com/cover/899/48593899/b_48593899.jpg)
2.7 字符串的模式查找
问题
你想要在String中搜索,查看其是否包含一个正则表达式。
解决方案
在一个字符串上调用.r方法可以创建一个Regex对象,如果想在一个字符串中查找一个Regex匹配的模式则使用其findFirstIn方法,如果想查找所有匹配的模式则使用其findAllIn方法。
为了验证上面的说法,首先需要为想要搜索的模式创建一个Regex,下面这个例子是查找一个或多个数字字符的序列:
![](https://epubservercos.yuewen.com/87A2C8/28235253302644106/epubprivate/OEBPS/Images/65_01.jpg?sign=1738954434-3nO9dgzHXMRW6PV4J2dEyuuQNavOJ5tK-0-92aea0b540f3b0bf58800765d70f5b85)
下一步,创建一个用来搜索的字符串样例:
![](https://epubservercos.yuewen.com/87A2C8/28235253302644106/epubprivate/OEBPS/Images/65_02.jpg?sign=1738954434-erlUnPfnQLhk1pHX7mkMdEqVWImrkk28-0-34268a3f252460cc5535437cfd5848f1)
findFirstIn方法将找到第一个匹配结果:
![](https://epubservercos.yuewen.com/87A2C8/28235253302644106/epubprivate/OEBPS/Images/65_03.jpg?sign=1738954434-jUgmfaFBorKVbyeQBEWiiNV6jtSJCyHF-0-7b47ed9a26926af4a42953af7488e989)
注意,这个方法的返回值是Option[String]。
接下来看看寻找多个匹配时使用的findAllIn方法:
![](https://epubservercos.yuewen.com/87A2C8/28235253302644106/epubprivate/OEBPS/Images/65_04.jpg?sign=1738954434-zCzClaeIAlJm5TPjmmlJHNVXRHX4ZLu0-0-27e3ec84acd7a5858c3d74f01b8eb8e4)
如上所示,findAllIn返回一个迭代器,可以在这个迭代器上循环访问每一个匹配的结果:
![](https://epubservercos.yuewen.com/87A2C8/28235253302644106/epubprivate/OEBPS/Images/65_05.jpg?sign=1738954434-Q2joRZS0MI5z8FYcnliSSXz2O4NMCXgL-0-2de00af5d55748edeb6103cb0b5554d0)
如果findAllIn没有找到任何结果,会返回一个空的迭代器,所以仍然可以调用其方法而不会抛出空指针异常。如果想将结果转换成一个Vector,则只要在其后面继续调用toVector即可:
![](https://epubservercos.yuewen.com/87A2C8/28235253302644106/epubprivate/OEBPS/Images/65_06.jpg?sign=1738954434-3qmj8eIqP7AGY89QXDJ85Ly9tseUUobM-0-1eefa3a27db3c4bc9c24031409d6ae04)
如果没有任何匹配,上面这种方式将产生一个空的Vector。其他方法如toList、toSeq和toArray在没有任何匹配时也是可用的。
讨论
在一个字符串上使用.r方法是创建一个Regex对象的最简单的方法。另一种方法是导入Regex类,创建一个Regex实例,然后以同样的方式使用该实例:
![](https://epubservercos.yuewen.com/87A2C8/28235253302644106/epubprivate/OEBPS/Images/65_07.jpg?sign=1738954434-lfhReuRh9Jh00lqM5ZkChRHuEMGDzKCi-0-95609fa87d87bac758293b1c37f19145)
虽然这么做会需要更多的代码,但是也更清晰明显,因为我发现自己很容易忽视掉字符串末尾的.r(然后会花几分钟来搞清楚代码竟然能正常工作的原因)。
关于findFirstIn的返回类型是Option的一些简要讨论
正如前面的解决方案里提到的,findFirstIn方法会找到例子中第一个匹配项然后返回Option[String]:
![](https://epubservercos.yuewen.com/87A2C8/28235253302644106/epubprivate/OEBPS/Images/66_01.jpg?sign=1738954434-JhNvhzg91MFKjo1DfV6s4yli0qW98WqG-0-9442202c32370aeede1e50e7d7a70ba1)
因为Option/Some/None模式将在24.6节介绍,所以这里不会详细讨论。Option简单来说是一个容纳0个或1个值的容器,在上面findFirstIn的例子里,如果它成功找到一个匹配,就会用Some把字符串"123"包起来,也就是Some("123")。如果在字符串中没有找到任何匹配项,就会返回一个None:
![](https://epubservercos.yuewen.com/87A2C8/28235253302644106/epubprivate/OEBPS/Images/66_02.jpg?sign=1738954434-vClDEmk091Xs3PMvTkBINypfeQgfTqqL-0-0bccc58fbd23b1caae05b34d447744e4)
总之,任何时候一个方法(a)被定义为返回Option[String],(b)保证不抛出异常,(c)保证终止(即不进入无限循环),它总是返回Some[String]或None。
另见
·请参阅Scala Regex类文档(https://oreil.ly/rdiBW),了解更多使用正则表达式的方法。
·请参阅24.6节,了解如何处理Option值的细节。