有没有办法让只有独特的比赛吗? 不使用列表或匹配后的地图,我想匹配的输出是唯一的时候了。
样品输入/输出:
String input = "This is a question from [userName] about finding unique regex matches for [inputString] without using any lists or maps. -[userName].";
Pattern pattern = Pattern.compile("\\[[^\\[\\]]*\\]");
Matcher matcher = pattern.matcher(rawText);
while (matcher.find()) {
String tokenName = matcher.group(0);
System.out.println(tokenName);
}
这将输出如下:
[userName]
[inputString]
[userName]
但我希望它输出如下:
[userName]
[inputString]
就在这里。 您可以结合负向前查找和向后引用:
"(\\[[^\\[\\]]*\\])(?!.*\\1)"
如果,这是由实际的模式匹配,不会再在字符串中出现的将只匹配。 实际上,这意味着你总是每场比赛的最后一次出现,所以你会得到他们以不同的顺序:
[inputString]
[userName]
如果订单是你的问题(即,如果它的关键首先出现命令他们),你不会只能够做到这一点使用正则表达式。 你需要一个可变长度的外观背后* *是什么,以及不被支持Java。
延伸阅读:
在一个通用的解决方案的一些注意事项
请注意,这将与他们的比赛是非零宽度的任何模式的工作原理。 一般的解决方法很简单:
(yourPatternHere)(?!.*\1)
(我离开了双反斜线,因为这仅适用于几种语言。)
如果你想让它与具有零宽度匹配(因为你只想知道一个位置,仅使用lookarounds出于某种原因)的模式工作,你可以这样做:
(zeroWidthPatternHere)(?!.+\1)
另外,还要注意(一般),你可能必须使用“单线”或“DOTALL”选项,如果你的输入可能包含换行(否则先行只会在当前行检查)。 如果你不能或者不想激活(因为你有包括不应该匹配换行符周期模式;或者,因为你使用JavaScript),这是一般的解决方案:
(yourPatternHere)(?![\s\S]*\1)
而为了让这个答案更广泛地适用,这里是你怎么能只匹配每场比赛的第一次出现(与可变长度lookbehinds发动机,如.NET):
(yourPatternHere)(?<!\1.*\1)
or
(yourPatternHere)(?<!\1[\s\S]*\1)