获得独特的正则表达式匹配结果(不使用地图或列表)(get unique regex matcher

2019-07-04 05:27发布

有没有办法让只有独特的比赛吗? 不使用列表或匹配后的地图,我想匹配的输出是唯一的时候了。

样品输入/输出:

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]

Answer 1:

就在这里。 您可以结合负向前查找和向后引用:

"(\\[[^\\[\\]]*\\])(?!.*\\1)"

如果,这是由实际的模式匹配,不会再在字符串中出现的将只匹配。 实际上,这意味着你总是每场比赛的最后一次出现,所以你会得到他们以不同的顺序:

[inputString]
[userName]

如果订单是你的问题(即,如果它的关键首先出现命令他们),你不会只能够做到这一点使用正则表达式。 你需要一个可变长度的外观背后* *是什么,以及不被支持Java。

延伸阅读:

  • Lookarounds
  • 反向引用

在一个通用的解决方案的一些注意事项

请注意,这将与他们的比赛是非零宽度的任何模式的工作原理。 一般的解决方法很简单:

(yourPatternHere)(?!.*\1)

(我离开了双反斜线,因为这仅适用于几种语言。)

如果你想让它与具有零宽度匹配(因为你只想知道一个位置,仅使用lookarounds出于某种原因)的模式工作,你可以这样做:

(zeroWidthPatternHere)(?!.+\1)

另外,还要注意(一般),你可能必须使用“单线”或“DOTALL”选项,如果你的输入可能包含换行(否则先行只会在当前行检查)。 如果你不能或者不想激活(因为你有包括不应该匹配换行符周期模式;或者,因为你使用JavaScript),这是一般的解决方案:

(yourPatternHere)(?![\s\S]*\1)

而为了让这个答案更广泛地适用,这里是你怎么能只匹配每场比赛的第一次出现(与可变长度lookbehinds发动机,如.NET):

(yourPatternHere)(?<!\1.*\1)
or
(yourPatternHere)(?<!\1[\s\S]*\1)


文章来源: get unique regex matcher results (without using maps or lists)