英文:
Is there a way to verify a regular expression has exactly one match in Java?
问题
我正在制作一个用于处理发票的正则表达式生成器,我想知道是否有一种方法可以知道我的正则表达式是否与文本的某个部分匹配且仅匹配一次。正则表达式本身并不是非常重要,我只想知道是否可以检查是否只有一个匹配而且没有更多的匹配。
我当然在使用java.util.regex
包中的Pattern
和Matcher
。
我尝试使用matcher.groupCount()
,但似乎行不通,因为它涉及的是组的数量而不是匹配的数量。
提前感谢您的回答。
英文:
i'm currently making a regex generator for some invoices, and I wanted to know if there is a way to know that my regular expression matched with one and only one part of the text. The regular expr itself is not really important, I just want to know if I can check there was only one match and no more.
I'm of course using Pattern
and Matcher
from java.util.regex
package.
I tried to use matcher.groupCount()
but that doesnt seem to do the trick because it involves group count not the matches count.
Thanks in advance for your answers.
答案1
得分: 0
你可以在这里使用String#matches
与一些前瞻逻辑:
String input = "The quick brown fox jumps over the lazy dog.";
if (input.matches("((?!\\bfox\\b).)*\\bfox\\b(?!.*\\bfox\\b).*")) {
System.out.println("MATCH");
}
上面使用的正则表达式是(String#matches
使用隐式的起始/结束锚点):
^((?!\\bfox\\b).)*\\bfox\\b(?!.*\\bfox\\b).*$
这将匹配第一个fox
出现,前提是后面的输入字符串中不会再出现fox
。
编辑:
上述答案可以通过使用(?s)
标志启用点号模式来跨行工作:
String input = "The quick brown\nfox jumps \tover the lazy dog.";
if (input.matches("(?s)((?!\\bfox\\b).)*\\bfox\\b(?!.*\\bfox\\b).*")) {
System.out.println("MATCH");
}
英文:
You could just use String#matches
here with some lookahead logic:
String input = "The quick brown fox jumps over the lazy dog.";
if (input.matches("((?!\\bfox\\b).)*\\bfox\\b(?!.*\\bfox\\b).*")) {
System.out.println("MATCH");
}
The above regex being used is (String#matches
uses implicit starting/ending anchors):
^((?!\bfox\b).)*\bfox\b(?!.*\bfox\b).*$
This will match a single first occurrence of fox
, provided that fox
does not occur anywhere else later in the input string.
Edit:
The above answer can be made to work across lines by enabling dot all mode using the (?s)
flag:
String input = "The quick brown\nfox jumps \tover the lazy dog.";
if (input.matches("(?s)((?!\\bfox\\b).)*\\bfox\\b(?!.*\\bfox\\b).*")) {
System.out.println("MATCH");
}
答案2
得分: 0
只需遍历匹配项并保持计数。
final Matcher matcher = Pattern.compile("[fm]oo").matcher(",foo,moo,");
int numMatches = 0;
String match = null;
while (matcher.find()) {
numMatches++;
match = matcher.group();
}
if (numMatches > 1) {
System.out.println("期望找到一个匹配项,实际找到 " + numMatches);
} else {
System.out.println(match);
}
如果您不关心有多少个匹配项,您可以在循环中设置条件,并且在找到第二个匹配项后使用`break`语句中断循环。
或者重构为一个实用方法。在这个实现中,我假设您不关心有多少个匹配项。
public static void main(String[] args) {
final Matcher matcher = Pattern.compile("[fm]oo").matcher(",foo,moo,");
System.out.println(
getSingleMatch(matcher)
.orElseThrow(() -> new RuntimeException("期望找到恰好一个匹配项"))
//或者根据需要处理失败
);
}
private static Optional<String> getSingleMatch(Matcher matcher) {
final boolean foundOnce = matcher.find();
if (!foundOnce) return Optional.empty();
final String firstMatch = matcher.group();
final boolean foundTwice = matcher.find();
return !foundTwice ? Optional.ofNullable(firstMatch) : Optional.empty();
}
英文:
Just iterate the matches and keep a count.
final Matcher matcher = Pattern.compile("[fm]oo").matcher(",foo,moo,");
int numMatches = 0;
String match = null;
while (matcher.find()) {
numMatches++;
match = matcher.group();
}
if (numMatches > 1) {
System.out.println("expected one match, found " + numMatches);
}
else {
System.out.println(match);
}
If you don't care how many matches there are, you can put a condition in the loop and break
as soon as you've found the 2nd one.
Or refactor to a util method. In this implementation, I presumed you didn't care about how many matches there are.
public static void main(String[] args) {
final Matcher matcher = Pattern.compile("[fm]oo").matcher(",foo,moo,");
System.out.println(
getSingleMatch(matcher)
.orElseThrow(() -> new RuntimeException("Expected exactly 1 match"))
//or handle the failure however use you like
);
}
private static Optional<String> getSingleMatch(Matcher matcher) {
final boolean foundOnce = matcher.find();
if (!foundOnce) return Optional.empty();
final String firstMatch = matcher.group();
final boolean foundTwice = matcher.find();
return !foundTwice ? Optional.ofNullable(firstMatch) : Optional.empty();
}
专注分享java语言的经验与见解,让所有开发者获益!
评论