Scala-使用正则表达式替换第二和第四次出现

时间:2019-04-30 09:16:21

标签: scala

我想在下面的字符串中将amt_2和amt_4替换为amt_ytd_2和amt_ytd_4。

scala> val a = "select amt_1, amt_2, amt_3, amt_4 from table"
a: String = select amt_1, amt_2, amt_3, amt_4 from table

scala> val reg = """(\d+)""".r
reg: scala.util.matching.Regex = (\d+)

我可以一次性替换所有的字符串,但是如何仅替换字符串中第二和第四出现的字符串?

scala> reg.replaceAllIn(a, "_ytd_$1")
res23: String = select amt__ytd_1, amt__ytd_2, amt__ytd_3, amt__ytd_4 from table

scala>

我尝试了以下类似操作,但未获得预期结果

scala> var x = 0
x: Int = 0

scala> reg.replaceAllIn(a, {x+=1; if(x%2==0) "ytd" else " " })
res24: String = select amt_ , amt_ , amt_ , amt_  from table

scala>

3 个答案:

答案 0 :(得分:4)

您可以在守卫条件下进行模式匹配。

"amt_(\\d+)".r.replaceAllIn(a, _ match {
    case m if m.group(1).toInt % 2 == 0 => s"amt__ytd_${m.group(1)}"
    case m                              => m.group(0)
  })
//res0: String = select amt_1, amt__ytd_2, amt_3, amt__ytd_4 from table

更新

您似乎想要第二和第四匹配,不一定是以_2_4结尾的匹配。试试这个。

//string to modify
val a = "select amt_1, amt_2, amt_3, amt_4 from table"

//all the matches
val ms = "amt_(\\d+)".r.findAllMatchIn(a).toVector

//modify 2nd & 4th match (i.e. at index 1 & 3) if they exist
Vector(1,3).foldRight(a)(
  (x,s) => ms.lift(x).fold(s)(m => s.patch(m.start(1), "_ydt_", 0)))
//res0: String = select amt_1, amt__ydt_2, amt_3, amt__ydt_4 from table

请注意,只有找到了这么多匹配项时,这才会修改索引3处的第4个匹配项。同样,对于索引为1的第二个匹配。因此,如果找到0个或1个匹配,则不会生成任何mod。如果找到2或3个匹配项,则仅制作1个mod(第二个匹配项)。

答案 1 :(得分:1)

尝试使用replaceSomeIn

val a = "select amt_1, amt_2, amt_3, amt_4 from table"

val reg = """(\d+)""".r

var c = 0
reg.replaceSomeIn(a, m => {
  c = c+1
  val x = m.group(0)
  if ( c == 2 || c == 4)
    Some("a")
  else 
    Some(x)
})

答案 2 :(得分:0)

val a = "select amt_1, amt_2, amt_3, amt_4 from table"

val reg = """((?=\d)(?=[^13]))""".r
reg.replaceAllIn(a, "_ytd_$1")

尝试一下