如何在 Scala 中将第 n 次出现的特殊字符(例如竖线定界符)替换为另一个字符?

How do I replace the nth occurrence of a special character, say, a pipe delimiter with another in Scala?

我是使用 Scala 的 Spark 新手,我需要用换行符替换第 n 次出现的定界符。

到目前为止,我已经成功地在 管道分隔符之后输入了一个新行。 我无法 替换 分隔符本身。

我的输入字符串是

val txt = "January|February|March|April|May|June|July|August|September|October|November|December"

println(txt.replaceAll(".\|", "[=10=]\n"))

以上语句生成以下输出。

January|
February|
March|
April|
May|
June|
July|
August|
September|
October|
November|
December

我参考了 https://salesforce.stackexchange.com/questions/189923/adding-comma-separator-for-every-nth-character 的建议,但是当我在花括号中输入数字时,我最终只在分隔符后的 2 个字符后添加换行符.

我希望我的输出如下所示。

January|February
March|April
May|June
July|August
September|October
November|December

如何更改我的正则表达式以获得所需的输出?

更新: 我的朋友建议我尝试以下语句

println(txt.replaceAll("(.*?\|){2}", "[=13=]\n"))

这产生了以下输出

January|February|
March|April|
May|June|
July|August|
September|October|
November|December

现在我只需要去掉每行末尾的管道符号。

您可以先使用“|”拆分字符串获取字符串数组,然后遍历它以执行所需的逻辑并根据需要获取输出。

val txt = "January|February|March|April|May|June|July|August|September|October|November|December"
val out = txt.split("\|")
var output: String = ""
for(i<-0 until out.length -1 by 2){
  val ref = out(i) + "|" + out(i+1) + "\n"
  output = output + ref
}
val finalout = output.replaceAll("\"\"","")  //just to remove the starting double quote
println(finalout)

您想将第二个柱 | 移到捕获组之外。

txt.replaceAll("([^|]+\|[^|]+)\|", "\n")
//val res0: String =
//  January|February
//  March|April
//  May|June
//  July|August
//  September|October
//  November|December

正则表达式解释(正则表达式不是 Scala)

  • ( - 启动捕获组
  • [^|] - 任何字符,只要不是小节 | 字符
  • [^|]+ - 1 个或多个(任何)非条形字符
  • \| - 后跟一个条形字符 |
  • [^|]+ - 后跟 1 个或多个非条形字符
  • ) - 关闭捕获组
  • \| - 后跟一个条形字符(不在捕获组中)
  • "\n" - 用第一个 </code> 捕获组替换整个匹配字符串(<code>[=24=] 是整个匹配字符串),然后是换行符

更新

对于 N 次重复的一般情况,正则表达式变得有点麻烦,至少如果您尝试使用单个正则表达式公式来做到这一点。

最简单的事情(不是最有效但代码简单)是遍历 String 两次。

val n = 5
txt.replaceAll(s"(\w+\|){$n}", "[=11=]\n")
   .replaceAll("\|\n", "\n")
//val res0: String =
//  January|February|March|April|May
//  June|July|August|September|October
//  November|December