scala 正则表达式,用于使用RNN获取所有键值对

sqougxex  于 5个月前  发布在  Scala
关注(0)|答案(4)|浏览(61)

我的输入总是看起来像这样,带有任意数量的键/值对:

"irrelevant part[identifier]key1=val1;key2=val2;key3=val3"

字符串
并且期望的最终结果是[key1, val1, key2, val2, key3, val3]
我能够通过\[identifier](.*)匹配并获取key1=val1;key2=val2;key3=val3,但我不知道如何获取由分号分隔的对。

9rygscc1

9rygscc11#

复杂正则表达式功能强大,但众所周知难以理解和维护,而且可能会变得非常慢。你似乎根本不需要它,我会这样做:

input
 .dropWhile(_ != ']')
 .tail
 .split(";")
 .map { _.split("=") }
 .collect { case Array(k,v) => k -> v }
 .toMap

字符串

zc0qhyus

zc0qhyus2#

您可以使用带有\G运算符的模式:

val text = "irrelevant part[identifier]key1=val1;key2=val2;key3=val3"
val regex = """(?:\G(?!^);|\[identifier])([\w-]+)=([^;]*)""".r
val results = (regex findAllIn text).matchData.map(x => (x.group(1), x.group(2))).toMap
println(results) // => Map(key1 -> val1, key2 -> val2, key3 -> val3)

字符串
参见this Scala demothis regex demo。* 详细信息 *:

  • (?:\G(?!^);|\[identifier])-前一个匹配的结束,然后是;字符,或[identifier]字符序列
  • ([\w-]+)-第1组:一个或多个单词或-字符
  • =-一个=字符,
  • ([^;]*)-第2组:除分号以外的任意零个或多个字符。
mitkmikd

mitkmikd3#

我认为你正在寻找的是所谓的“积极的回头看”:More technical description
匹配主表达式 * 之前的组,但不将其包含在结果中。*
[From]
(?<= ...“regex”... )
所以(?<=[identifier])(.*)在你的例子中得到key1=val1;key2=val2;key3=val3
然后,您可以使用split,然后使用另一个简单的正则表达式来获得Key/ValueTuplesArrayMap

val regexResult: String = "key1=val1;key2=val2;key3=val3"
val splitKeyValuePairs: Array[String] = result.split(";")

val keyValueRegex: Regex = """(.*)=(.*)""".r

val keyValueTupleArray: Array[(String, String)] = splitKeyValuePairs.collect{
    case keyValueRegex(k, v) => (k, v)
}

val keyValueMap: Map[String, String] = keyValueTupleArray.toMap

字符串

wa7juj8i

wa7juj8i4#

如果你想要key1, val1, key2, val2, key3, val3]作为给定字符串格式的输出:

val input = "irrelevant part[identifier]key1=val1;key2=val2;key3=val3"

val result = input.split("""\[identifier]""") match {
  case Array(_, t) => t.split("[=;]")
  case _ => Array.empty
}

字符串
输出

Array(key1, val1, key2, val2, key3, val3)


另一种选择是使用split,然后使用grouped(2)并从元组中创建Map:

val result = input.split("""\[identifier]""") match {
  case Array(_, t) =>
    t.split("[=;]")
      .grouped(2)
      .collect { case Array(k, v) => k -> v }
      .toMap
  case _ => Map.empty
}


或者使用regex匹配te [identifier]之后的键=值对,直到字符串的结尾:

val pattern = """\[identifier]([^\s;=]+=[^\s;=]*(?:;[^\s;=]+=[^\s;=]*)*)$""".r

val result = pattern.findFirstMatchIn(input) match {
  case Some(v) =>
    v.group(1)
      .split("[=;]")
      .grouped(2)
      .collect { case Array(k, v) => k -> v }
      .toMap
  case _ => Map.empty
}


最后两个代码示例将返回

val result: Map[String,String] = Map(key1 -> val1, key2 -> val2, key3 -> val3)

相关问题