Java/Kotlin:标记字符串忽略嵌套引号的内容

Java/Kotlin: Tokenize a string ignoring the contents of nested quotes

我想用空格分隔一个字符,但将空格保留在引号内(以及引号本身)。问题是,引号可以嵌套,而且我需要对单引号和双引号都这样做。所以,从行 this "'"is a possible option"'" and ""so is this"" and '''this one too''' and even ""mismatched quotes" 我想得到 [this, "'"is a possible option"'", and, ""so is this"", and, '''this one too''', and, even, ""mismatched quotes"].

这个问题已经有人问过,但不是我要问的确切问题。 Here 有几种解决方案:一个使用匹配器(在本例中 """x""" 将被拆分为 [""", x"""],所以这不是我需要的)和 Apache Commons(与 """x""" 但不使用 ""x"",因为它采用前两个双引号并使用 x 保留最后两个)。也有人建议编写一个函数来手动执行此操作,但这是最后的选择。

您可以使用以下正则表达式实现:["']+[^"']+?["']+。使用该模式,您可以像这样检索要拆分的索引:

val indices = Regex(pattern).findAll(this).map{ listOf(it.range.start, it.range.endInclusive) }.flatten().toMutableList()

剩下的就是用子字符串构建列表。这里是完整的函数:

fun String.splitByPattern(pattern: String): List<String> {

    val indices = Regex(pattern).findAll(this).map{ listOf(it.range.start, it.range.endInclusive) }.flatten().toMutableList()

    var lastIndex = 0
    return indices.mapIndexed { i, ele ->

        val end = if(i % 2 == 0) ele else ele + 1 // magic

        substring(lastIndex, end).apply {
            lastIndex = end
        }
    }
}

用法:

val str = """
this "'"is a possible option"'" and ""so is this"" and '''this one too''' and even ""mismatched quotes"
""".trim()

println(str.splitByPattern("""["']+[^"']+?["']+"""))

输出:

[this , "'"is a possible option"'", and , ""so is this"", and , '''this one too''', and even , ""mismatched quotes"]

Kotlin's playground 上试用!