Java正则表达式中match()和find()之间的区别


249

我试图了解两者之间的区别 matches()find()

根据Javadoc,(据我了解), matches()即使找到了所要查找的内容也将搜索整个字符串,并find()在找到所要查找的内容时停止。

如果这个假设是正确的,我看不到您何时要使用 matches()find(),除非您要计算找到的匹配项的数量,否则代替。

我认为String类应该具有 find()而不是matches()作为内置方法。

总结一下:

  1. 我的假设正确吗?
  2. 什么时候matches()代替有用find()

2
请注意,find()多次调用可能会针对同一对象返回不同的结果Matcher。请参阅下面的答案。
L. Holanda

Answers:


300

matches尝试将表达式与整个字符串匹配,^$在模式的开头和结尾隐式添加a ,这意味着它将不查找子字符串。因此,此代码的输出:

public static void main(String[] args) throws ParseException {
    Pattern p = Pattern.compile("\\d\\d\\d");
    Matcher m = p.matcher("a123b");
    System.out.println(m.find());
    System.out.println(m.matches());

    p = Pattern.compile("^\\d\\d\\d$");
    m = p.matcher("123");
    System.out.println(m.find());
    System.out.println(m.matches());
}

/* output:
true
false
true
true
*/

123是的子字符串,a123b因此该find()方法输出true。matches()只能“看到” a123b,它与不相同123,因此输出false。


25
这个答案是误导的。matchers()不只是一个find()带有隐含的^和$的a。请注意,.find()多次调用可能会产生不同的结果(如果没有以开头)reset(),而matches()始终会返回相同的结果。请参阅下面的答案。
L. Holanda

80

matches如果整个字符串与给定的模式匹配,则返回true。find尝试找到与模式匹配的子字符串。


35
您可以说这matches(p)find("^" + p + "$")更清楚一样。
jensgram

4
仅是一个阐明答案的示例:使用字符串“ 123abc123”的“ [az] +”将无法使用matchs(),但将使用find()成功。
bezmax 2010年

3
@Max确实"123abc123".matches("[a-z]+")会失败"123abc123".find("^[a-z]+$")。我的意思是,这matches()完全匹配,就像find()开始和结束锚一样。
jensgram

5
Pattern.compile("some pattern").matcher(str).matches()等于Pattern.compile("^some pattern$").matcher(str).find()
AlexR 2010年

3
@AlexR / @jensgram:...("some pattern").matcher(str).matches()不是正好等于...("^some pattern$").matcher(str).find()这只是在第一次调用正确的。请参阅下面的答案。
L. Holanda

62

matches()仅当完整字符串匹配时才返回true。 find()将尝试在与正则表达式匹配的子字符串中查找下一个匹配项。注意对“下一个”的强调。这意味着find()多次调用的结果可能会不同。此外,通过使用find()可以调用start()以返回匹配子字符串的位置。

final Matcher subMatcher = Pattern.compile("\\d+").matcher("skrf35kesruytfkwu4ty7sdfs");
System.out.println("Found: " + subMatcher.matches());
System.out.println("Found: " + subMatcher.find() + " - position " + subMatcher.start());
System.out.println("Found: " + subMatcher.find() + " - position " + subMatcher.start());
System.out.println("Found: " + subMatcher.find() + " - position " + subMatcher.start());
System.out.println("Found: " + subMatcher.find());
System.out.println("Found: " + subMatcher.find());
System.out.println("Matched: " + subMatcher.matches());

System.out.println("-----------");
final Matcher fullMatcher = Pattern.compile("^\\w+$").matcher("skrf35kesruytfkwu4ty7sdfs");
System.out.println("Found: " + fullMatcher.find() + " - position " + fullMatcher.start());
System.out.println("Found: " + fullMatcher.find());
System.out.println("Found: " + fullMatcher.find());
System.out.println("Matched: " + fullMatcher.matches());
System.out.println("Matched: " + fullMatcher.matches());
System.out.println("Matched: " + fullMatcher.matches());
System.out.println("Matched: " + fullMatcher.matches());

将输出:

发现:错误
找到:正确-位置4
找到的:是-位置17
找到:正确-排名20
发现:错误
发现:错误
匹配:错误
-----------
找到:正确-位置0
发现:错误
发现:错误
符合:true
符合:true
符合:true
符合:true

因此,即使没有find()Matcher对象重置也要多次调用,即使将正则表达式用完整的字符串包围起来^并与之$匹配也要小心。


2
非常有帮助的伴侣
DockYard

6

find()将考虑针对正则表达式的子字符串,matches()将视为完整表达式。

find() 仅当表达式的子字符串与模式匹配时才返回true。

public static void main(String[] args) {
        Pattern p = Pattern.compile("\\d");
        String candidate = "Java123";
        Matcher m = p.matcher(candidate);

        if (m != null){
            System.out.println(m.find());//true
            System.out.println(m.matches());//false
        }
    }

3

matches();不缓冲,而是find()缓冲。find()首先搜索到字符串的末尾,对结果进行索引,然后返回布尔值和相应的索引。

这就是为什么当你有一个像

1:Pattern.compile("[a-z]");

2:Pattern.matcher("0a1b1c3d4");

3:int count = 0;

4:while(matcher.find()){

5:count++: }

4:使用模式结构的regex引擎将通读您的整个代码(由索引指定的索引到索引,regex[single character]以找到至少一个匹配项。如果找到这样的匹配项,将对其进行索引,然后根据以下内容执行循环如果不执行索引计算,则返回索引结果;否则,则matches()不会执行while语句,因为匹配的字符串的第一个字符不是字母。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.