我的要求是转换一些文本消息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)}
的方法就不太优雅了。
是否有更好的阅读方式/更简洁的方式来访问第一个匹配项?
答案 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]}
。
另外,请注意:
.messageid=
(请参见(.*\.messageid=)
)X
或Y
,因此无需捕获(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);
确保模式应与整个字符串匹配,否则将不匹配,并且字符串将按原样返回,而无需进行任何修改。答案 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++)
}
这样,您可以确保替换与所需输入完全匹配的行,并保留其他行但不替换。