假设我有一个具有一个捕获组的正则表达式。在scala中有一种简单的方法可以用替换字符串替换此捕获组吗?我只能找到用一些内容替换整个正则表达式的功能,其中可能包括一个捕获组,但完整的正则表达式匹配不包含在替换的字符串中。举一个具体的例子:
val p = """^[bf]oo: '(.*)'"""r
println(p.replaceFirstGroup("foo: 'replace me'", "asdf")) // something like this
带输出
foo: 'asdf'
答案 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)