代码基本上是:
T, &, &, T, &, T
我期待前瞻是贪婪的,但它正在返回数组:
T, &&, T, &, T
我的目标是:
"(?=\\w|&&?)"
分裂和前瞻是否可行?
我尝试了以下拆分正则表达式值,但结果仍然不是吝啬的&符号:
"(?=\\w|&{1,2})"
public class DateConverter{
public static SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
public static Date convertStringToDate(final String str){
try{
return DATE_FORMAT.parse(str);
} catch(Exception ex){
//TODO: Log exception
return null;
}
}
public static String convertDateToString(final Date date){
try{
return DATE_FORMAT.format(date);
} catch(Exception ex){
//TODO: Log exception
return null;
}
}
}
答案 0 :(得分:2)
它已经贪婪了,但我认为你误解了你的分裂是如何运作的。问题是你在考虑角色而不是它们之间的空间(这是正则表达式可以远离你的地方之一)。
您要求分割字符串中的下一个字符是单词字符或一系列&符号的位置。在你的字符串中,让我们标记满足该字符串的地方:
T|&|&|T|&|T
在第一个T和第一个&符号之间的空格中,下一个字符是&符号(匹配(?=&)
,它在你的正则表达式中有效),两个&符号之间的空格也匹配同样的原因。 &符号和第二个T之间的空格也匹配(匹配(?=\w)
),依此类推。
split函数将测试字符串中的每个空格,以确定它是否是分割位置的候选者。要做你想做的事,你必须小心使用前瞻,这样我们就不允许在一串&符号的中间分裂。
有多种方法可以克服这个问题; WiktorStribiżew提供了一条适用于他的评论的建议。
通常使用后视来检查您是否重复不需要的角色会起作用,或者如果可能的话,您可以使用后视来识别匹配的位置,并使用前瞻来避免不希望的重复。例如,如果我们希望将所有字符分开,将重复的字符放在一起,则可以(?<=(.))(?!\\1)
将您的示例拆分为T, &&, T, &, T
。
答案 1 :(得分:1)
答案 2 :(得分:1)
Lookarounds不能贪婪或不情愿,他们只是检查左侧(lookbehind)和右侧(lookahead)的相邻文本是否与环视子模式匹配。如果匹配,并且环视为正,则匹配空位置。如果没有锚定环视,则字符串中的每个位置都将针对环视中的模式进行测试,甚至是开头和结尾。请参阅此截图(显示您的(?=\w|&&?)
):
由于环视是零宽度断言并且它不消耗字符,因此测试所有位置(在每个字符之前和结尾处)。因此,您可以获得每个角色之间的匹配。
(?=\w|&&?)
检查T
之前的第一个位置:它与\w
匹配,因此该位置匹配(请参阅第一个|
)。然后是T
之前的第一个&
之后的下一个位置。它符合&&
。然后,正则表达式引擎继续检查第一个&
和第二个&
之后的位置。它匹配,因为后面有一个&
。这样,我们匹配到最后。结束位置不匹配,因为未跟&
或单词字符。
您可以使用另一种环视来限制环视中的模式,以避免在输入字符串中匹配特定的位置。
(?=\w|(?<!&)&)
^^^^^^
(?<!&)&
模式将与之前没有其他&
的{{1}}匹配。请参阅regex demo。
&
环视解决方案是通用解决方案。如果我们要考虑当前的情况,你肯定可以缩短&#34;模式为String[] result = "T&&T&T".split("(?=\\w|(?<!&)&)");
System.out.println(Arrays.toString(result));
// => [T, &&, T, &, T]
(也将find a match at the end of the string,尽管Java String#split
将安全地从结果数组中删除尾随的空元素),该模式匹配非单词和单词字符之间的所有位置,也如果字符串的开头/结尾有一个单词字符,则在字符串的开头/结尾处。如果备选方案(例如正则表达式中的\b
和\w
)属于同一类型(例如,两个都是单词字符),则无法使用。
答案 3 :(得分:0)
看起来你想在不同的字符之间进行分割,所以一般来说:
String[] parts = input.split("(?<=T)(?=&)|(?<=&)(?=T)");
但在这种情况下,除了开头/结尾外,您可以拆分字边界:
String[] parts = input.split("(?<=.)\b(?=.)");