访问比赛结果的更好方法?

时间:2018-09-18 12:55:18

标签: regex kotlin

我的要求是转换一些文本消息ID。输入为

a.messageid=X0001E
b.messageid=Y0001E

任务是将其变成

a.messageid=Z00001E
b.messageid=Z00002E

换句话说:获取每行的第一部分(例如:a.),并附加一个略有不同的id。

我当前的解决方案:

val matcherForIds = Regex("(.*)\\.messageid=(X|Y)\\d{4,6}E")  
var idCounter = 5

fun transformIds(line: String): String {
    val result = matcherForIds.matchEntire(line) ?: return line
    return "${result.groupValues.get(1)}.messageid=Z%05dE".format(messageCounter++)
}

可行,但是找到我如何首先匹配"${result.groupValues.get(1)}的方法就不太优雅了。

是否有更好的阅读方式/更简洁的方式来访问第一个匹配项?

2 个答案:

答案 0 :(得分:1)

没有单独的功能,您可能会得到结果:

val line = s.replace("""^(.*\.messageid=)[XY]\d{4,6}E$""".toRegex()) { 
    "${it.groupValues[1]}Z%05dE".format(messageCounter++) 
}

但是,由于需要将format messageCounter放入结果中,所以不能只使用字符串替换模式,也不能摆脱${it.groupValues[1]}

另外,请注意:

  • 您可以通过使用三引号引起来的字符串文字来消除双反斜杠
  • 如果将零件捕获到组1中,则无需在替换中添加.messageid=(请参见(.*\.messageid=)
  • 由于以后不再使用XY,因此无需捕获(X|Y),因此,[XY]可以替换为更高效的字符类^。 / li>
  • $ const QString PING_PATH = "C:/Windows/System32/ping.exe"; QStringList pingArguments << "192.168.1.1"; QProcess *pingProcess = new QProcess(this); pingProcess->startDetached(PING_PATH, pingArguments); 确保模式应与整个字符串匹配,否则将不匹配,并且字符串将按原样返回,而无需进行任何修改。

请参见Kotlin demo online

答案 1 :(得分:1)

也许不是您真正想要的东西,但是也许是。如果您首先确保(过滤)感兴趣的行并仅替换需要替换的行,例如使用以下转换函数:

val matcherForIds = Regex("(.*)\\.messageid=(X|Y)\\d{4,6}E")
val idRegex = Regex("[XY]\\d{4,6}E")
var idCounter = 5

fun transformIds(line: String) = idRegex.replace(line) {
  "Z%05dE".format(idCounter++)
}

使用以下过滤器:

"a.messageid=X0001E\nb.messageid=Y0001E"
  .lineSequence()
  .filter(matcherForIds::matches)
  .map(::transformIds)
  .forEach(::println)

如果还有其他相关的字符串要保留,那么以下内容也是可行的,但不如最后的解决方案那么好:

"a.messageid=X0001E\nnot interested line, but required in the output!\nb.messageid=Y0001E"
  .lineSequence()
  .map {
    when {
      matcherForIds.matches(it) -> transformIds(it)
      else -> it
    }
  }
  .forEach(::println)

或者(现在只复制Wiktors正则表达式,因为它已经包含了我们所需要的(从行^到行$的末尾完全匹配,等等):

val matcherForIds = Regex("""^(.*\.messageid=)[XY]\d{4,6}E$""")
fun transformIds(line: String) = matcherForIds.replace(line) {
  "${it.groupValues[1]}Z%05dE".format(idCounter++)
}

这样,您可以确保替换与所需输入完全匹配的行,并保留其他行但不替换。