scala 在捕获组上拆分

scala split on capturing group

我试图仅在正则表达式的捕获组上拆分字符串,但我似乎在整个匹配上拆分。

我想在 | 上拆分 hi|my~~|~|name is bob,在 ~

前面加上零或任意偶数

所以我的预期输出是 Array(hi, my~~, ~|name is bob)

我正在使用正则表达式 "(?<!~)(?:~~)*(\|)"

但是 "hi|my~~|~|name is bob".split("(?<!~)(?:~~)*(\|)") 正在返回 Array[String] = Array(hi, my, ~|name is bob),因为它在 my 之后拆分整个 ~~|,而不仅仅是 | 之前的 ~~.

例如比较:

scala> "(?<!~)(?:~~)*(\|)".r.findAllIn("hi|my~~|~|name is bob").foreach(println)
|
~~|

scala> "(?<!~)(?:~~)*(\|)".r.findAllIn("hi|my~~|~|name is bob").matchData foreach { m => println(m.group(1)) }
|
|

编辑:

一些背景和说明:

我正在尝试将字符串列表序列化为由 | 分隔的单个字符串。我不能保证 |(或与此相关的任何字符)不会出现在单个字符串中。

为了实现所需的功能,我想转义所有出现的 |。我选择了 ~ 作为我的转义符。在我逃脱 | 之前,我需要逃脱 ~

一旦我转义了所有内容,我就可以使用 | 加入列表,以获得代表我的原始字符串列表的单个字符串。

然后为了将单个字符串解析回原始列表,我只需要在未转义的 |'s. I have to be careful because something like ~~| is actually an unescaped pipe even though it contains ~|. This is because the escape character is itself escaped, which means it was just a "tilda" in one of my original strings and is not meant to function as an "escape". In other words I had a string ending in ~, and it is now escaped into ~~ and joined with the next string in the list by a '|'.

上拆分

好的,所以如果我的初始字符串列表是 ["hi","my~","|name is bob"],我将首先转义所有 ~ 以获得 ["hi","my~~","|name is bob"]。现在我将转义所有 | 以获得 ["hi","my~~","~|name is bob"],最后我将加入 | 以获得单个字符串:

"hi|my~~|~|name is bob"

现在,如果我想反转它,我需要首先拆分未转义的 |,即前面有零个或偶数个 ~ 的任何 | .所以如果我能用我的正则表达式实现这个(到目前为止我在我的捕获组中正确捕获这个,但我只是不知道如何只应用组而不是完整的 ~~| 匹配例如到拆分),那么我会得到["hi","my~~","~|name is bob"]。现在我只是取消转义我的 ~,取消转义我的 |,然后我回到了我原来的输入:

["hi","my~","|name is bob"]

您需要所有 ~ 都成为后视组的一部分,因为 split 在正则表达式的 整体 匹配上拆分,不仅仅是一组,即使该组是非捕获组。一个更简单的例子:

"asdf" split "(?:s)" //Array(a, df)

look-behind 组不是匹配的一部分,所以你想把你的前缀标准放在那里。基本上,您需要将您的解决方案包装在另一个后视组中。理想情况下,您需要:

"""(?<=(?<!~)(~~)*)\|"""

但不幸的是 Java 不支持任意长度的后视组。解决方法是:

"""(?<=(?<!~)(~~){0,10})\|"""

只要 ~ 的个数不超过 20 个,它就可以用于偶数个 ~。如果这是一个问题,您可以增加 10。

如果嵌套的回顾令人困惑,您也可以使用等效的:

"""(?<![^~]~(~~){0,10})\|"""