使用模式匹配,您只能在字符串中获取一个匹配项。因此,一个解决方案是直接使用正则表达式 API。
解决方案 1:简单的两步法
您可以抓取所有出现的word+one or more sequences of 1+ spaces and then words,然后使用spaces-comma-spaces 模式分割匹配项:
val fruits = "fruits: apple, orange, banana and vegetables: carrots, potatos, cabbage"
val regex = """\w+(?:,\s*\w+)+""".r
val results = (regex findAllIn fruits).map(_ split """\s*,\s*""").toList
for (l <- results) println(l.toList)
输出:
List(apple, orange, banana)
List(carrots, potatos, cabbage)
请参阅Scala demo。
解决方案 2:“一个正则表达式来统治它们”
如果单词是使用findAllIn 的以逗号分隔的连续单词的一部分,则您可以使用单个正则表达式来抓取任何单个单词:
val fruits = "fruits: apple, orange, banana"
val regex = """(?:\G(?!^)\s*,\s*|(?=\w+(?:,\s*\w+)+))(\w+)""".r
val results = (regex findAllIn fruits).matchData.map(_ group 1).toList
println(results)
// => List(apple, orange, banana)
见Scala demo
详情
-
(?:\G(?!^)\s*,\s*|(?=\w+(?:,\s*\w+)+)) - 两种选择之一:
-
\G(?!^)\s*,\s* - 上一场比赛的结束,然后是一个用可选空格括起来的逗号
-
| - 或
-
(?=\w+(?:\s*,\s*\w+)+) - 该位置后跟 1+ 个单词字符,然后是 1+ 个逗号重复,用可选空格括起来,然后是 1+ 个单词字符
-
(\w+) - 第 1 组:一个或多个单词字符(字母、数字或 _s)
请参阅regex demo。
模式匹配只找到一个匹配项
请注意,您可以使用 match 块解析您的字符串,以提取这串逗号分隔的单词,然后将它们拆分:
val fruits = "fruits: apple, orange, banana."
val regex = """(\w+(?:\s*,\s*\w+)+)""".r.unanchored
val results = fruits match {
case regex(m) => m.split("""\s*,\s*""").toList
case _ => List("")
}
println(results) // => List(apple, orange, banana)
见another Scala demo。
注意:
- 这里,
.unanchored 是返回部分匹配项所必需的
- 整个模式被一个捕获组包裹,因为我们需要使用该组访问
match 块中找到的文本
-
.split("""\s*,\s*""") 用逗号分隔找到的文本,其中包含 0+ 个空格
- 如果没有匹配,
case _ => List("") 将返回一个空列表。