【问题标题】:scala split on capturing groupscala 在捕获组上拆分
【发布时间】:2015-03-26 11:01:13
【问题描述】:

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

我想在| 上拆分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)) }
|
|

编辑

一些背景和说明:

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

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

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

然后稍后将单个字符串解析回原始列表,我只需要在未转义的| 上进行拆分。我必须小心,因为像~~| 这样的东西实际上是一个未转义的管道,即使它包含~|。这是因为转义字符本身是转义的,这意味着它只是我原始字符串之一中的“tilda”,而不是用作“转义”。换句话说,我有一个以~ 结尾的字符串,现在它转义为~~,并通过“|”与列表中的下一个字符串连接。

好的,所以如果我的初始字符串列表是["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"]。现在我简单地取消我的~'s,取消我的|,然后我回到了我原来的输入:

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

【问题讨论】:

  • 我不理解预期的输出:Array(hi, my~~, ~|name is bob)。为什么分隔符是它的一部分?为什么不是 Array(hi, my, name is bob)?
  • 该 |在我的预期输出中不是分隔符。这是一个|那是我最初的输入,需要转义,所以我没有将它与分隔符混淆。请参阅我的编辑以获得更多说明。

标签: regex scala split


【解决方案1】:

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

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

look-behind 组不属于匹配项,因此您希望将前缀条件放入其中。基本上,您需要将您的解决方案包装在另一个后视组中。理想情况下,您希望:

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

但不幸的是,Java 不支持任意长度的后视组。作为一种解决方法,您可以这样做:

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

只要有 20 个或更少,这将适用于偶数个 ~s。如果这是一个问题,你可以增加 10。

如果嵌套的look-behinds令人困惑,您也可以使用等效的:

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

【讨论】:

  • "hi|my~~|~|name is bob" split """(?&lt;=(~~){0,10})\|""" 产生 Array(hi, my~~, ~, name is bob) 而不是 Array(hi, my~~, ~|name is bob)
  • 非常好的答案。感谢您抽出宝贵时间完成这项工作。
猜你喜欢
  • 2014-05-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-05
  • 1970-01-01
相关资源
最近更新 更多