最简单的搜索方式替换Scala中的正则表达式组

时间:2014-06-17 02:09:23

标签: scala

假设我有一个具有一个捕获组的正则表达式。在scala中有一种简单的方法可以用替换字符串替换此捕获组吗?我只能找到用一些内容替换整个正则表达式的功能,其中可能包括一个捕获组,但完整的正则表达式匹配不包含在替换的字符串中。举一个具体的例子:

val p = """^[bf]oo: '(.*)'"""r
println(p.replaceFirstGroup("foo: 'replace me'", "asdf")) // something like this

带输出

foo: 'asdf'

2 个答案:

答案 0 :(得分:2)

使用lookahead和lookbehind(定义为java.util.regex.Pattern),以及String.replaceFirst可以获得所需的结果:

val p = """(?<=^[bf]oo: ').*(?=')"""
println("foo: 'replace me'".replaceFirst(p, "asdf"))
// => foo: 'asdf'

前瞻(?=)和lookbehind (?<=)都匹配文字而不将其作为匹配结果的一部分。这就是为什么replaceFirst仅替换前瞻或后瞻中包含的 not 部分,即单引号之间的.*

或者(我可能更喜欢这个解决方案),您可以匹配所有部分,并使用$ {引用您希望在替换字符串中保持不变的部分{ {1}} 语法:

{group-id}

我知道技术上并没有取代第一个捕获组,但是前瞻和后瞻总是让我觉得很脏。 (我知道,具有讽刺意味吗?我们已经在这里使用正则表达式!)


  

我希望得到别的东西,因为前瞻限制了前瞻部分中正则表达式的复杂性,并且匹配许多组会为提取器和替换代码增加额外的复杂性。

这实现起来有点麻烦(你必须编写一些额外的代码),但它会让你的提取器整洁,同时也避免了前瞻/外观:

val p = """(^[bf]oo: ')(.*)(')"""
println("foo: 'replace me'".replaceFirst(p, "$1asdf$3"))
// => foo: 'asdf'

答案 1 :(得分:0)

也许replaceSomeIn方法在这里可能会有用吗?

(引用他们来自ScalaDoc的例子):

import scala.util.matching.Regex._

val map = Map("x" -> "a var", "y" -> """some $ and \ signs""")
val text = "A text with variables %x, %y and %z."
val varPattern = """%(\w+)""".r
val mapper = (m: Match) => map get (m group 1) map (quoteReplacement(_))
val repl = varPattern replaceSomeIn (text, mapper)

在你的情况下:

val p = """^([bf]oo): '(.*)'"""r
val map = Map("foo" -> "foo: 'asdf'")
val lines = List("boo: 'bar' and beyond","foo: 'yuck' whatever")
val mapper = (m: Match) => map get (m group 1) map (quoteReplacement(_))

scala> val repl = text map { line => p replaceSomeIn(line, mapper) }
m: boo: 'bar' boo
m: foo: 'yuck' foo
repl: List[String] = List(boo: 'bar' and beyond, foo: 'asdf' whatever)