如果我有一个由字符分隔的字符串,可以这么说:
a-b-c
并且我想保留分隔符,我可以使用后视和前视来保留分隔符本身,例如:
string.split("((?<=-)|(?=-))");
结果
-
a
-
-
-
b
-
-
-
c
现在,如果其中一个分隔符被转义,如下所示:
a-b\-c
我想兑现这次转义,我想出了使用这样的正则表达式:
((?<=-(?!(?<=\\-))) | (?=-(?!(?<=\\-))))
因此
string.split("((?<=-(?!(?<=\\\\-)))|(?=-(?!(?<=\\\\-))))"):
现在,这有效并导致:
-
a
-
-
-
b\-c
(我稍后用 string.replace("\\", "");
删除反斜杠,我还没有找到将其包含在正则表达式中的方法)
我的问题是理解问题。
按照我的理解,正则表达式就是,
split ((if '-' is before (unless ('\-' is before))) or (if '-' is after (unless ('\-' is before))))
为什么最后一部分不应该是“除非\
在之前”?如果“-”在后面,则意味着我们位于“\”和“-”之间,因此只有 \
应该在之前,而不是 \\-
,但如果我更改正则表达式以反射(reflect)这样的情况,它就不起作用:
((?<=-(?!(?<=\\-))) | (?=-(?!(?<=\\))))
结果:a
, -
, b\
, -c
这是什么原因呢?我的推理错误在哪里?
最佳答案
虽然这并不能真正回答问题,但这解释了环视是如何工作的。
Lookarounds 是 anchor :它们不消耗文本,而是在输入文本中查找位置。您的正则表达式可以用更简单的方式编写:
(?<=-)(?<!\\-)|(?=-)(?<!\\)
这里有所有四种环视:正向和负向前瞻、正向和负向前瞻。
完整的正则表达式如下:
(?<=-) # Find a position where what precedes is a dash
(?<!\\-) # Find a position where what precedes is not \-
| # Or
(?=-) # Find a position where what follows is a dash
(?<!\\) # Find a position where what precedes is not a \
请注意术语“位置”。请注意, anchor 根本不会在文本中前进。
现在,如果我们尝试将该正则表达式与 a-b\-c
进行匹配:
# Step 1
# Input: | a-b\-c|
# Position: |^ |
# Regex: | (?<=-)(?<!\\-)|(?=-)(?<!\\)|
# Position: |^ |
# No match, try other alternative
# Input: | a-b\-c|
# Position: |^ |
# Regex: |(?<=-)(?<!\\-)| (?=-)(?<!\\)|
# Position: | ^ |
# No match, regex fails
# Advance one position in the input text and try again
# Step 2
# Input: |a -b\-c|
# Position: | ^ |
# Regex: | (?<=-)(?<!\\-)|(?=-)(?<!\\)|
# Position: |^ |
# No match, try other alternative
# Input: |a -b\-c|
# Position: | ^ |
# Regex: |(?<=-)(?<!\\-)| (?=-)(?<!\\)|
# Position: | ^ |
# Match: a "-" follows
# Input: |a -b\-c|
# Position: | ^ |
# Regex: |(?<=-)(?<!\\-)|(?=-) (?<!\\)|
# Position: | ^ |
# Match: what precedes is not a \
# Input: |a -b\-c|
# Position: | ^ |
# Regex: |(?<=-)(?<!\\-)|(?=-)(?<!\\) |
# Position: | ^|
# Regex is satisfied
这是一种不使用拆分且不使用环视的替代方案:
[a-z]+(\\-[a-z]+)*|-
您可以在Pattern
中使用此正则表达式并使用Matcher
:
public static void main(final String... args)
{
final Pattern pattern
= Pattern.compile("[a-z]+(\\\\-[a-z]+)*|-");
final Matcher m = pattern.matcher("a-b\\-c");
while (m.find())
System.out.println(m.group());
}
关于java - 分割字符串,同时保留除转义分隔符之外的分隔符(正则表达式),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17545881/