具有优先级的Java正则表达式匹配模式
我使用的是一个系统,&后跟一个字母或数字表示一种颜色。具有优先级的Java正则表达式匹配模式,java,regex,Java,Regex,我使用的是一个系统,&后跟一个字母或数字表示一种颜色。 可以跟在后面的有效字符是[A-Fa-fK-Ok-or0-9] 例如,我有一个字符串&这是一个测试&bstring,它有丰富的&ehas&4&lof&7种颜色。 我希望在每个&x处拆分,同时将&x保留在字符串中。 因此,我在正则表达式中使用了正向前瞻 (?=(&[A-Fa-fK-Ok-or0-9]) 工作完全正常,输出为: &aThis is a test &bstring that &ehas plenty &4 &lof &7co
可以跟在后面的有效字符是
[A-Fa-fK-Ok-or0-9]
例如,我有一个字符串&这是一个测试&bstring,它有丰富的&ehas&4&lof&7种颜色。
我希望在每个&x处拆分,同时将&x保留在字符串中。因此,我在正则表达式中使用了正向前瞻
(?=(&[A-Fa-fK-Ok-or0-9])
工作完全正常,输出为: &aThis is a test &bstring that &ehas plenty &4 &lof &7colors. &这是一种考验 &B宣布 &埃哈斯很多 &4 &lof &7种颜色。 问题是,不应该拆分两个相邻的&x实例的spot,该行应该是
&4&lof
有人知道我可以使用什么正则表达式,这样当两个of&x相邻时,它们就可以匹配在一起了。颜色代码的两个实例应优先于单个实例。我尝试过:
{
}
我们可以在所有子字符串的开头添加&以获得您要查找的结果。类似的内容将起作用 它使用该方法并将有效行放入
ArrayList
(例如colorLines
)
问题说明
问题是已知的:您需要标记一个字符串,该字符串可能包含连续的分隔符,您需要在结果字符串列表/数组中将其作为单个项保留
使用lookaround(s)进行拆分在这里没有帮助,因为未配置的lookaround测试字符串中的每个位置。如果模式匹配字符串中的任何字符,则可以使用\G
运算符,但实际情况并非如此甚至添加一个+
量词-s0.split((?=(?:&[a-Fa-fK-Ok-or0-9])+)”
就是因为这样
解决方案
使用匹配而不是拆分,并使用构建块保持可读性
String s0 = "This is a text&aThis is a test &bstring that &ehas plenty &4&lof &7colors.";
String colorRx = "&[A-Fa-fK-Ok-or0-9]";
String nonColorRx = "[^&]*(?:&(?![A-Fa-fK-Ok-or0-9])[^&]*)*";
Pattern pattern = Pattern.compile("(?:" + colorRx + ")+" + nonColorRx + "|" + nonColorRx);
Matcher m = pattern.matcher(s0);
List<String> res = new ArrayList<>();
while (m.find()){
if (!m.group(0).isEmpty()) res.add(m.group(0)); // Add if non-empty!
}
System.out.println(res);
// => [This is a text, &aThis is a test , &bstring that , &ehas plenty , &4&lof , &7colors.]
请参阅。它实际上基于您的初始模式:首先,我们匹配所有颜色代码(1个或多个序列),然后匹配0+个不是颜色序列起点的字符(即颜色代码以外的所有字符串)。[^&]*(?:&(?[a-Fa-fK-Ok-or0-9])[^&]*
子模式是(?)的同义词(?:(?!&[A-Fa-fK-Ok-or0-9])*
当您需要匹配某些文本块而不是指定的文本块时,它非常方便,但由于它会消耗资源(特别是在Java中),因此最好使用展开版本
因此,模式-
(?:“+colorRx+”+“+nonColorRx+”|“+nonColorRx
)匹配1+colorRx
子模式,后跟可选的nonColorRx
子模式,或者(|
)零个或多个nonColorRx
子模式。组(0).isEmpy()
不允许在结果数组中使用空字符串。那么为什么不在?=(和&[在你的正则表达式中?因为整个想法是将它们作为一个整体而不是分开匹配在一起。你说“$a$b”是两个,“$a$b”是一个,所以正则表达式不应该更像“(?=(&[a-Fa-fK-Ok-or0-9])”,中间有一个空格吗(和&?然后你只需要特别注意字符串中的第一个字符。我认为这是最简单和直接的方法。在我看来,你可以只添加一个反向查找:(?I)(?=&[a-fk-o0-9])(?。换句话说,在没有颜色代码的任何颜色代码上拆分。
&aThis is a test
&bstring that
&ehas plenty
&4&lof
&7colors.
String mainStr = "&aThis is a test &bstring that &ehas plenty &4&lof &7colors";
String [] arr = mainStr.split("&");
List<String> colorLines = new ArrayList<String>();
String lastColor = "";
for (String s : arr)
{
s = s.trim();
if (s.length() > 0)
{
if (s.length() == 1)
{
lastColor += s;
}
else
{
colorLines.add(lastColor.length() > 0 ? lastColor + s : s);
lastColor = "";
}
}
}
for (String s : colorLines)
{
System.out.println(s);
}
aThis is a test
bstring that
ehas plenty
4lof
7colors
String s0 = "This is a text&aThis is a test &bstring that &ehas plenty &4&lof &7colors.";
String colorRx = "&[A-Fa-fK-Ok-or0-9]";
String nonColorRx = "[^&]*(?:&(?![A-Fa-fK-Ok-or0-9])[^&]*)*";
Pattern pattern = Pattern.compile("(?:" + colorRx + ")+" + nonColorRx + "|" + nonColorRx);
Matcher m = pattern.matcher(s0);
List<String> res = new ArrayList<>();
while (m.find()){
if (!m.group(0).isEmpty()) res.add(m.group(0)); // Add if non-empty!
}
System.out.println(res);
// => [This is a text, &aThis is a test , &bstring that , &ehas plenty , &4&lof , &7colors.]
(?:&[A-Fa-fK-Ok-or0-9])+[^&]*(?:&(?![A-Fa-fK-Ok-or0-9])[^&]*)*|[^&]*(?:&(?![A-Fa-fK-Ok-or0-9])[^&]*)*