![Scala编程实战(原书第2版)](https://wfqqreader-1252317822.image.myqcloud.com/cover/899/48593899/b_48593899.jpg)
2.9 使用模式匹配提取字符串
问题
你想要提取一个字符串中符合指定的正则表达式模式的一个或多个部分。
解决方案
将想提取的正则表达式(regular-expression,regex)模式进行定义,并使用小括号括起来,这样就可以将其作为正则表达式组来提取。步骤如下,首先定义所需的模式:
![](https://epubservercos.yuewen.com/87A2C8/28235253302644106/epubprivate/OEBPS/Images/67_04.jpg?sign=1738954732-8NxFvhWUCX9sMhCz8XhOzFtZIuAsY2Ut-0-4cc2a4a2006e9c17aa0da6b6c64e4a6a)
这将把pattern创建成一个scala.util.matching.Regex类的实例。这个正则表达式用文字表达则是:一个或多个数字紧跟一个空格再紧跟一个或多个字母表字符。
接下来就是从目标字符串中提取这组正则表达式:
![](https://epubservercos.yuewen.com/87A2C8/28235253302644106/epubprivate/OEBPS/Images/67_05.jpg?sign=1738954732-SxHZ9PWE10Kl51MhTOoJuixsA0gXv0qE-0-6049687a1baebd6f8636f7f025ae839a)
如注释所示,这段代码从给定的字符串中提取了数字字段和字母字段,并将其作为两个独立的变量count和fruit。
讨论
这里展示的语法可能会让人感觉有点不寻常,因为这里好像把pattern定义为val字段了两次,但是在使用match表达式的真实例子中,这种语法更加方便,可读性也更好。
试想一下,有一个像谷歌一样的搜索引擎,可以用各种短语来搜索电影。为方便起见,可以输入任何下面这些短语来获得科罗拉多州博尔德附近上映的电影列表:
![](https://epubservercos.yuewen.com/87A2C8/28235253302644106/epubprivate/OEBPS/Images/68_01.jpg?sign=1738954732-e0GW1VXdnYzy3b45YhB8N2ztSacZZili-0-2a31bb3213d3ca0109578eec98633535)
可以允许使用所有这些短语的一种方法是定义一系列正则表达式模式来与它们匹配。只要定义好表达式,然后尝试将用户输入的任何内容与所有可能的表达式进行匹配即可。
举一个例子,可以试想一下,只允许下面两种模式:
![](https://epubservercos.yuewen.com/87A2C8/28235253302644106/epubprivate/OEBPS/Images/68_02.jpg?sign=1738954732-9nwqxVmzP8j40QZ8GjCR5GztdAduF7hw-0-b8fcb8588d095157ba8aca8f4f8d9450)
这些模式将与下面这些字符串匹配:
![](https://epubservercos.yuewen.com/87A2C8/28235253302644106/epubprivate/OEBPS/Images/68_03.jpg?sign=1738954732-TOVJ9IUzvqMVsITApOD7nRL2ODQ06VOC-0-19bfd7d28e2ecd43ac0f972c382cdfb3)
一旦定义了允许匹配的正则表达式模式,就可以用一个match表达式将它们与用户输入的任何文本进行匹配。在下面的例子中,调用了一个名为getSearchResults的虚构的方法,该方法在发生匹配时返回一个Option[List[String]]:
![](https://epubservercos.yuewen.com/87A2C8/28235253302644106/epubprivate/OEBPS/Images/68_04.jpg?sign=1738954732-0yezeB7r7PpQMUqebshbQK9DxuQ6iiKF-0-59d0c772d25de1a687308b5ac5de9dd9)
如上所示,这种语法可以让match表达式的可读性更好,对于要匹配的两种模式,都要调用getSearchResults方法的重载版本,在第一种情况下传递zip字段,在第二种情况下传递city和state字段。
值得注意的是,使用这种技术,正则表达式必须与整个用户输入相匹配。以下字符串使用所示的正则表达式模式将失败,因为它们在行尾有一个空格:
![](https://epubservercos.yuewen.com/87A2C8/28235253302644106/epubprivate/OEBPS/Images/69_01.jpg?sign=1738954732-8iUiIUJzKEQMpQxIfSWtyWfzToSyC3xP-0-f3c299b8927081056c9c58ba472fd08c)
可以通过修剪输入字符串来解决这个问题,或者也可以像实际应用中那样使用更复杂的正则表达式。
想象一下,你可以在许多不同的情况下使用这种模式匹配技术,包括匹配日期和时间格式、街道地址、人名以及许多其他情况。
另见
·请参阅4.6节,了解更多match表达式的例子。
·在match表达式中,你可以看到scala.util.matching.Regex被用作一个提取器。提取器将在7.8节中讨论。