如何在非转义分隔符上正确拆分?
How to properly split on a non escaped delimiter?
我有以下示例字符串:
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
嵌入标志选项
(?:\.|[^\|])+
- \
的一次或多次重复,然后是任何一个字符,或除 \
和 |
. 之外的任何字符
参见 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 个转义反斜杠,我相信在大多数情况下应该足够了,但您可能想先测试一下。我仍然推荐第一个解决方案。
详情:
(?<=
- 正面回顾的开始:
(?<!\)
- 没有紧跟 \
的位置
(?:\{2}){0,1000}
- 双反斜杠出现零到一千次
)
- 正回顾结束
\|
- 一个 |
字符。
我有以下示例字符串:
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
嵌入标志选项(?:\.|[^\|])+
-\
的一次或多次重复,然后是任何一个字符,或除\
和|
. 之外的任何字符
参见 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 个转义反斜杠,我相信在大多数情况下应该足够了,但您可能想先测试一下。我仍然推荐第一个解决方案。
详情:
(?<=
- 正面回顾的开始:(?<!\)
- 没有紧跟\
的位置
(?:\{2}){0,1000}
- 双反斜杠出现零到一千次
)
- 正回顾结束\|
- 一个|
字符。