带三引号的字符串位于带三引号的字符串内部

Kse*_*nia 5 string kotlin

我在带三引号的字符串内部使用带三引号的字符串:

fun main(args: Array<String>) {    
    val firstStr = """

    OLOLO
    """.trimIndent()

    val secondStr = """
    $firstStr
    new added text
    """.trimIndent()

    println("The firstStr is $firstStr")
    println("The secondStr is $secondStr")
}
Run Code Online (Sandbox Code Playgroud)

我得到以下输出:

The firstStr is 
OLOLO
The secondStr is     
OLOLO
    new added text
Run Code Online (Sandbox Code Playgroud)

我很困惑为什么缩进保留在最后一行(" new added text")...因为我预计该trimIndent()方法必须修剪所有缩进(正如文档注释所说,该方法

检测所有输入行的公共最小缩进,将其从每一行中删除,如果第一行和最后一行为空白,则还删除它们(注意空白与空的区别)。

同时我可以使用带有默认参数(“|”)的trimMargin()来剪切这个缩进:

fun main(args: Array<String>) {    
    val firstStr = """

    OLOLO
    """.trimIndent()

    val secondStr = """
    $firstStr
    |new added text
    """.trimMargin()

    println("The firstStr is $firstStr")
    println("The secondStr is $secondStr")
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我得到以下输出:

The firstStr is 
OLOLO
The secondStr is     
OLOLO
new added text
Run Code Online (Sandbox Code Playgroud)

但我不明白为什么trimIndent()不修剪那个缩进......

Yon*_*bbs 9

问题实际上并不在trimIndent. 它与原始字符串文字在包含参数时的工作方式有关。你可以这样开始:

{
    val firstStr = """

    OLOLO
    """.trimIndent()
}
Run Code Online (Sandbox Code Playgroud)

其结果是firstStr具有以下值:

"
OLOLO"
Run Code Online (Sandbox Code Playgroud)

然后用以下代码注入secondStr

{
    val secondStr = """
    $firstStr
    new added text
    """.trimIndent()
}
Run Code Online (Sandbox Code Playgroud)

现在想象一下您实际上输入了此内容而不是使用参数值。你可以这样做(我将用下划线替换一些空格以澄清一些事情):

{
    val secondStr = """

____OLOLO
    new added text
    """.trimIndent()
}
Run Code Online (Sandbox Code Playgroud)

那一切都会很好。但是,当该值被注入到原始字符串文字中时,实际上并没有发生什么,因为它不知道您想要在我上面放置下划线的位置放置空格。就系统而言,您只是告诉它只需输入回车符即可OLOLO。所以实际上发生的是生成的值( trimIndent调用之前)是这样的:

{
    val secondStr = """

OLOLO
    new added text
    """.trimIndent()
}
Run Code Online (Sandbox Code Playgroud)

然后,当trimIndent开始处理它时,它所做的第一件事就是尝试寻找共同的缩进,但它找不到,因为其中一行 ( OLOLO) 没有缩进。所以它无能为力。这就是为什么前面的空白new added text仍然存在的原因)。

如果您在 的实现中放置一个断点trimIndent来查看接收器是什么(即开始工作secondStr之前的值是什么),您就可以看到这一点。trimIndent

所以你的解决方案是正确的。添加管道字符并使用trimMargin. 管道意味着添加的文本之前没有 4 个前导空格,这就是它正确修剪所有文本的原因。


l'L*_*L'l 5

奇怪的现象trimIdent()似乎是由空行开头引起的。尽管开头的空行毫无疑问似乎让一切都变得不正常,但它对整个开头的制表符和空格的一致性也有点挑剔。鉴于此,您可以\n在您的代码中包含换行符 ( )println作为解决方法。

fun main(args: Array<String>) {    

    val firstStr =
        """
            OLOLO
        """.trimIndent()

    val secondStr = 
        """
            $firstStr
            new added text
        """.trimIndent()

    println("The firstStr is \n$firstStr")
    println("The secondStr is \n$secondStr")

}
Run Code Online (Sandbox Code Playgroud)

输出

The firstStr is
OLOLO
The secondStr is
OLOLO
new added text
Run Code Online (Sandbox Code Playgroud)

String.trimIndent() : String 检测所有输入行的公共最小缩进,将其从每一行中删除,如果第一行和最后一行为空白,则还删除它们(注意空白与空的区别)。请注意,空行不会影响检测到的缩进级别。如果存在没有前导空白字符的非空行(根本没有缩进),则常见缩进为 0,因此此函数不会更改缩进。

不保留原始行结尾。

下面的陈述:“注意空白与空的区别”,可能是解开谜题的关键,尽管目前还不清楚它们的含义;绝对是奇怪的行为(也许是错误?)。