【问题标题】:Scala pattern match repeated regex groupsScala 模式匹配重复的正则表达式组
【发布时间】:2019-07-14 05:07:42
【问题描述】:

如何通过正则表达式模式从一些重复值中提取列表,例如

val fruits = "fruits: apple, orange, banana"
fruits match {
  case regex(fruits) => // where `fruits` is `List[String] = List(apple, orgran, banana)`
}

除了

case regex(rawFruits) => rawFruits.split(",")

更新:

我对模式匹配特别感兴趣,因为输入字符串值中可能有多个列表

【问题讨论】:

  • 请告诉我以下两种解决方案是否适合您。
  • 我看到你在我上面的评论之后访问了 SO。你有时间检查我的建议吗?请提供反馈,否则,我们无法知道哪种方法适合您。

标签: regex scala pattern-matching


【解决方案1】:

使用模式匹配,您只能在字符串中获取一个匹配项。因此,一个解决方案是直接使用正则表达式 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 _ =&gt; List("") 将返回一个空列表。

【讨论】:

  • 谢谢,非常有趣的解决方案。但是第一个不是完全模式匹配,另一个是在原始问题中提到的。你知道如何进行模式匹配吗?例如对于这种情况,字符串值中可能有多个列表
  • @ntviet18 第一个是解决方案。它不必看起来像那样,您可以抓住\w+(?:\s+\w+)+ 的匹配项,然后与\s*,\s* 进行拆分,与第二个解决方案相同。它将更具可读性。您不能使用模式匹配来获得多个匹配项。
  • @ntviet18 为答案添加了更多内容。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-04-09
  • 2014-04-04
  • 1970-01-01
  • 1970-01-01
  • 2019-11-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多