从scala字符串中提取标记的快速方法

Sah*_*een 1 regex string scala

鉴于其具有键 - 值对的集合(具有类型键 - 值对的顺序不固定,键 - 值对的数目不固定的)一阶字符串:

val s = "key1: val1, key2: (val2.1, val2.2, val2.3), key3: (), key4: val4"
Run Code Online (Sandbox Code Playgroud)

我需要把它们拉成一个不可变的地图,如:

Map("key1" -> "val1",
  "key2" -> "(val2.1, val2.2, val2.3)",
  "key3" -> "()",
  "key4" -> "val4")
Run Code Online (Sandbox Code Playgroud)

我试过这个:

val kvMap = s.split(", ").map(_.split(": ")).map(t => t(0) -> t(1)).toMap
Run Code Online (Sandbox Code Playgroud)

但这失败了,因为在括号中和键值对之间使用了相同的分隔符(逗号).

我可以使用迭代使用堆栈但是想要避免这种情况.

我也尝试写一个正则表达式,可以帮助我做到这一点,但可以使它只适用于1对:

scala>  val MyPattern = "([^=]*):(.*)".r
Pattern: scala.util.matching.Regex = ([^=]*):(.*)
                           ^
scala> val MyPattern(k, v) = "key: value"
k: String = key
v: String = " value"
Run Code Online (Sandbox Code Playgroud)

我正在寻找一种功能性的方法来完成这项操作.

Wik*_*żew 5

如果你的键值对没有嵌套的括号,你可以使用正则表达式用逗号+空格未遵循比其他任何字符分割()高达):

""", (?![^()]*\))""".r
Run Code Online (Sandbox Code Playgroud)

请参阅正则表达式演示

说明:

  • , - 仅在以下情况下匹配逗号和空格...
  • (?![^()]*\))- 没有跟随非)和非)(0次或更多次)跟随文字)(即,如果没有跟随某些东西+ )).

如果您想尝试匹配的方法:

"""([^=:]*):\s*(.*?),?\s*(?=$|\w+:)""".r
Run Code Online (Sandbox Code Playgroud)

这个演示

细节:

  • ([^=:]*)- 第1组捕获除了=和之外的0+个字符:(可能*应该替换为,+因为键不能为空)
  • :\s* - 带有0+空格的冒号
  • (.*?),?\s*- 任何字符,但新行尽可能少(第2组 (.*?)),后跟可选,和0+空格...
  • (?=$|\w+:) - 随后是字符串结尾或1+单词字符和冒号.