kotlin String :: replace删除转义序列?

时间:2018-03-02 17:47:46

标签: regex kotlin escaping

我正在使用正则表达式尝试一些字符串操作,但我没有得到预期的输出

var myString = "/api/<user_id:int>/"
myString.replace(Regex("<user_id:int>"), "(\\d+)")

这应该给我一些/api/(\d+)/,但我得到/api/(d+)/

但是,如果我直接创建一个转义字符串,例如var a = "\d+" 我得到正确的输出\d+(我可以进一步用它来创建一个正则表达式模式)
这是由于String::replace的工作原理吗? 如果是这样,这不是一个错误,为什么它会删除我的转义序列?

3 个答案:

答案 0 :(得分:5)

要替换文字字符串,请使用:

myString.replace(Regex("<user_id:int>"), Regex.escapeReplacement("(\\d+)"))

有关详细信息,这就是kotlin Regex.replace正在做的事情:

  Pattern nativePattern = Pattern.compile("<user_id:int>");
  String m = nativePattern.matcher("/api/<user_id:int>/").replaceAll("(\\d+)");

  -> m = (d+) 

来自Matcher.replaceAll() javadoc:

  

请注意替换中的反斜杠()和美元符号($)   字符串可能会导致结果与正确的结果不同   作为文字替换字符串处理。可以对待美元符号   作为对如上所述的捕获的子序列的引用,和   反斜杠用于替换替换中的文字字符   字符串。

上面对Regex.escapeReplacement的调用就是这样,将(\\d+)转为(\\\\d+)

答案 1 :(得分:2)

您正在使用.replace重载,它将正则表达式作为第一个参数,因此,第二个参数被解析为正则表达式替换模式。在正则表达式替换模式中,\ char是特殊的,它可以逃避美元符号以被视为文字美元符号。因此,正则表达式替换模式中的字面反斜杠应该加倍。

您可以使用

myString.replace(Regex("<user_id:int>"), """(\\d+)""")

每当您必须使用正则表达式进行搜索和替换并且替换模式是动态值时,您应该使用Regex.escapeReplacement(请参阅GUIDO's answer)。

但是,您正在用另一个文字值替换文字值,您不必在此处使用正则表达式:

myString.replace("<user_id:int>", """(\d+)""")

this Kotlin demo屈服于/api/(\d+)/

请注意使用原始字符串文字,其中反斜杠被解析为文字反斜杠。

答案 2 :(得分:0)

作为正则表达式引擎的替换看到它被插值为双引号字符串 每个正则表达式引擎都是如此。

这是为了区分控制代码,例如制表符换行符或回车符。

这里没什么特别的。

所以作为引擎的替换想要看到(\\d+)

语言插入相同的内容。

最终结果repl_str = "(\\\\d+)"