我正在使用Java和正则表达式,需要将一些数据拆分为多个实体。在我的输入中,单引号字符(')指定实体的结尾,除非其前面是转义字符,它是一个问号(?)。
我的RegEx是(?<!\\?)\\'
,我正在使用扫描仪将输入拆分为单独的实体。因此以下案例正常运作:
Hello'There becomes 2 entities: Hello and There
Hello?'There remains 1 entity: Hello?'There
然而,当我遇到我想逃避问号的情况时,它不起作用。所以:
Hello??'There should become 2 entities: Hello?? and There
Hello???'There should become 1 entity: Hello???'There
Hello????'There should become 2 entities: Hello???? and There
Hello?????'There should become 1 entity: Hello????'There
Hello?????There should become 1 entity: Hello????There
Hello??????There should become 1 entity: Hello?????There
因此,规则是如果存在偶数个问号,后跟引号,则应该拆分。如果存在奇数个问号,那么它不应该分开。
有人可以帮我修复我的正则表达式(希望有解释!)来处理多个案例吗?
谢谢,
菲尔
答案 0 :(得分:3)
尝试使用此表达式来匹配偶数情况:(?<=[^\?](?>\?\?){0,1000})'
(?<=...)'
是一个积极的外观,即每个'
前面有(?<=
和)
之间的表达式匹配(?>\?\?)
是一个包含2个连续问号的原子组(?>\?\?){0,1000}
表示可以有0到1000个这样的组。请注意,您不能编写(?>\?\?)*
,因为表达式需要具有最大长度(最大组数)。但是,您应该能够大量增加上限,具体取决于表达式的其余部分[^\?](?>\?\?)...
表示2个问号的组必须以某个字符开头,但不能带问号(否则您将匹配奇数情况)答案 1 :(得分:2)
请勿使用split()
。这似乎是一个明显的解决方案,但匹配实体本身要比匹配分隔符更容易。大多数启用正则表达式的语言都有内置的方法,比如Python的findall()
或Ruby的scan()
,但在Java中我们仍然坚持编写样板文件。这是一个例子:
Pattern p = Pattern.compile("([^?']|\\?.)+");
String[] inputs = {
"Hello??'There",
"Hello???'There",
"Hello????'There",
"Hello?????'There",
"Hello?????There",
"Hello??????There"
};
for (String s : inputs)
{
System.out.printf("%n%s :%n", s);
Matcher m = p.matcher(s);
while (m.find())
{
System.out.printf(" %s%n", m.group());
}
}
输出:
Hello??'There :
Hello??
There
Hello???'There :
Hello???'There
Hello????'There :
Hello????
There
Hello?????'There :
Hello?????'There
Hello?????There :
Hello?????There
Hello??????There :
Hello??????There
任意最大长度的噱头托马斯使用,除了是一个恶心的黑客(没有进攻意图,托马斯!),是不可靠的,因为他们不断引入处理这些东西的Pattern.java代码中的错误。但是,不要将此解决方案视为另一种解决方法; lookbehinds永远不应该是你的第一个手段,即使是像.NET这样可靠且无限制地工作的风格。
答案 2 :(得分:0)
您确定要使用正则表达式吗?如果您的字符串相对较小和/或执行时间不是一个大问题,您可以使用字符串生成器和循环来计算&#34;?&#34; e.g。
//Your String
String x = "Hello??'World'Hello?'World";
StringBuilder sb = new StringBuilder();
//Holds your splits
ArrayList<String> parts = new ArrayList<String>();
int questionmarkcount = 0;
int _isEven;
for (char c : x.toCharArray()) {
if (c == '?') {
questionmarkcount++;
sb.append(c);
} else if (c == '\'') {
_isEven = questionmarkcount % 2;
//if there are an even number of '? or none
if (_isEven == 0 || questionmarkcount == 0) {
//add the current split, reset the ? count and clear the String builder
parts.add(sb.toString());
sb.delete(0, sb.length());
questionmarkcount = 0;
} else {
//append the question mark, no split is needed
sb.append(c);
//start counting from the beginning
questionmarkcount = 0;
}
} else {
sb.append(c);
}
}
parts.add(sb.toString());
在循环结束时,部件ArrayList将保存所有拆分。如果在&#39;之前有偶数个问号,则当前代码将被拆分。