问题描述
我有以下示例字符串:
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
解决方法
提取方法
您可以使用匹配方法,因为它最稳定,并且允许任意数量的转义 \
字符。你可以使用
(?s)(?:\\.|[^\\|])+
参见regex demo。 详情:
-
(?s)
-Pattern.DOTALL
嵌入式标志选项 -
(?:\\.|[^\\|])+
- 一次或多次重复\
和任何一个字符,或除\
和|
之外的任何字符。
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 正则表达式中使用 约束宽度 后视模式支持,并使用限制量词如 {0,1000}
而不是 *
量词。解决方法看起来像
String s = "A|B\\|C\\\\|D\\\\\\|E\\\\\\\\|F";
String[] results = s.split("(?<=(?<!\\\\)(?:\\\\{2}){0,1000})\\|"); System.out.println(Arrays.toString(results));
注意 (?:\\{2}){0,1000}
部分只允许最多 1000 个转义反斜杠,这在大多数情况下应该足够了,我相信,但您可能想先测试一下。我仍然推荐第一种解决方案。
详情:
-
(?<=
- 正面回顾的开始:-
(?<!\\)
- 没有紧跟在\
前面的位置 -
(?:\\{2}){0,1000}
- 双反斜杠出现零到一千次
-
-
)
- 正向后视结束 -
\|
- 一个|
字符。