【问题标题】:How to properly split on a non escaped delimiter?如何正确拆分非转义分隔符?
【发布时间】:2021-01-26 12:35:41
【问题描述】:

我有以下示例字符串:

A|B\|C\\|D\\\|E\\\\F

与 |是分隔符,\ 是转义字符。 正确的拆分应如下所示:

A
B\|C\\
D\\\|E\\\\
F

如果分隔符或转义符由多个字符组成,我还需要这个逻辑普遍适用。

我已经有一个在正确位置拆分的正则表达式,但它没有产生所需的输出:

正则表达式:

(?<!\Q\\E)(?:(\Q\\\E)*)\Q|\E

输出:

A
B\|C
D\\\|E
F

我通常在这里测试:https://regex101.com/,但我在 java 中工作,所以我有更多的能力。

还尝试了以下没有正面结果的方法(在网页上不起作用,但在 java 中只是不会产生所需的结果):

(?=(\Q\\\E){0,5})(?<!\Q\\E)\Q|\E

【问题讨论】:

  • 你的意思是你的输入是A|B\|C\\|D\\\|E\\\\|F
  • 是的(虽然还不是字符串格式) Java 语句:"A|B\\|C\\\\|D\\\\\\|E\\\\\\\\ |F".split("proper_regex_here")
  • 不要使用split,它不会像提取方法那样稳定。

标签: java regex escaping delimiter


【解决方案1】:

提取方法

您可以使用匹配方法,因为它是最稳定的并且允许任意数量的转义 \ 字符。你可以使用

(?s)(?:\\.|[^\\|])+

请参阅regex demo详情

  • (?s) - Pattern.DOTALL 嵌入标志选项
  • (?:\\.|[^\\|])+ - 一次或多次重复\,然后是任何一个字符,或除\| 之外的任何字符。

Java demo

String s = "A|B\\|C\\\\|D\\\\\\|E\\\\\\\\|F";
Pattern pattern = Pattern.compile("(?:\\\\.|[^\\\\|])+", Pattern.DOTALL);
Matcher matcher = pattern.matcher(s);
List<String> results = new ArrayList<>();
while (matcher.find()){
    results.add(matcher.group());
} 
System.out.println(results); 
// => [A, B\|C\\, D\\\|E\\\\, F]

拆分方法(split 的解决方法)

您可以(ab)在 Java 正则表达式中使用 constrained-width 后向模式支持,并使用限制量词,如 {0,1000} 而不是 * 量词。一种变通方法看起来像

String s = "A|B\\|C\\\\|D\\\\\\|E\\\\\\\\|F";
String[] results = s.split("(?<=(?<!\\\\)(?:\\\\{2}){0,1000})\\|"); System.out.println(Arrays.toString(results));

this Java demo

注意(?:\\{2}){0,1000} 部分最多只能允许 1000 个转义反斜杠,我相信这在大多数情况下就足够了,但您可能想先对此进行测试。我仍然推荐第一个解决方案。

详情

  • (?&lt;= - 积极回顾的开始:
    • (?&lt;!\\) - 前面没有紧跟 \ 的位置
    • (?:\\{2}){0,1000} - 双反斜杠出现零到一千次
  • ) - 积极的后视结束
  • \| - | 字符。

【讨论】:

  • 虽然这回答了问题的标题,但我的问题可能被问得有点不正确。我特别需要一个正则表达式,我可以将它放在 split 函数中,并且可以使用多个字符作为分隔符和转义符。
  • @FelixUnverzagt 我建议使用 solutions 而不是 workarounds
  • 非常感谢第二种方法正在起作用(遗憾的是,我需要这种逻辑,因为它是更大的正则表达式逻辑的一部分)。如果以后有时间考虑如何更换其他部件,我会尝试采用第一种方法
猜你喜欢
  • 2011-05-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-15
  • 1970-01-01
相关资源
最近更新 更多