Isa*_*aac 8 java regex unique matcher pattern-matching
有没有办法只获得独特的比赛?在匹配后不使用列表或映射,我希望匹配器输出立即是唯一的.
样本输入/输出:
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);
}
Run Code Online (Sandbox Code Playgroud)
这将输出以下内容:
[userName]
[inputString]
[userName]
Run Code Online (Sandbox Code Playgroud)
但我希望它输出以下内容:
[userName]
[inputString]
Run Code Online (Sandbox Code Playgroud)
Mar*_*der 17
就在这里.您可以结合使用否定前瞻和反向引用:
"(\\[[^\\[\\]]*\\])(?!.*\\1)"
Run Code Online (Sandbox Code Playgroud)
只有在您的实际模式匹配的情况下,才会在字符串中再次出现.实际上,这意味着你总是得到每场比赛的最后一次出现,所以你会以不同的顺序得到它们:
[inputString]
[userName]
Run Code Online (Sandbox Code Playgroud)
如果订单对您来说是个问题(即,如果首次订购它们是至关重要的),您将无法仅使用正则表达式执行此操作.你需要一个可变长度的外观**,而Java不支持.
进一步阅读:
关于一般解决方案的一些注释
请注意,这适用于匹配宽度为非零的任何模式.一般解决方案很简单:
(yourPatternHere)(?!.*\1)
Run Code Online (Sandbox Code Playgroud)
(我省略了双反斜杠,因为这只适用于几种语言.)
如果您希望它与具有零宽度匹配的模式一起使用(因为您只想知道某个位置并且仅出于某种原因使用了外观),您可以这样做:
(zeroWidthPatternHere)(?!.+\1)
Run Code Online (Sandbox Code Playgroud)
此外,请注意(通常)您可能必须使用"singleline"或"dotall"选项,如果您的输入可能包含换行符(否则前瞻只会检查当前行).如果您不能或不想激活它(因为您的模式包含不应与换行符匹配的句点;或者因为您使用JavaScript),这是一般解决方案:
(yourPatternHere)(?![\s\S]*\1)
Run Code Online (Sandbox Code Playgroud)
为了使这个答案得到更广泛的应用,以下是如何只匹配每个匹配的第一个匹配项(在具有可变长度lookbehinds的引擎中,如.NET):
(yourPatternHere)(?<!\1.*\1)
or
(yourPatternHere)(?<!\1[\s\S]*\1)
Run Code Online (Sandbox Code Playgroud)