正则表达式模式区分字母时,它不应该?

时间:2016-11-21 01:41:11

标签: java regex

我正在编写一个正则表达式,用于练习的简单用户名验证。虽然我确信这种模式可能存在其他问题,但如果有人能够解释这种看似奇怪的行为,我希望如此。

import java.io.*;
import java.util.*;
import java.text.*;
import java.math.*;
import java.util.regex.*;

public class userRegex{
   public static void main(String[] args){
      Scanner in = new Scanner(System.in);
      int testCases = Integer.parseInt(in.nextLine());
      while(testCases>0){
         String username = in.nextLine();
         String pattern = "([[:alpha:]])[a-zA-Z_]{7,29}";
 Pattern r = Pattern.compile(pattern);
         Matcher m = r.matcher(username);

         if (m.find( )) {
            System.out.println("Valid");
         } else {
            System.out.println("Invalid");
         }
         testCases--;
      }
   }
}

当我输入时:

2
dfhidbuffon
dfdidbuffon

编译器应返回:

Valid
Valid

但相反,它会返回

Valid
Invalid

为什么它区分第三个字母的差异" h"或" d"在每个用户名中?

编辑:添加@Draco18s和@ruakh的建议,但是,我仍然得到同样的奇怪行为。

3 个答案:

答案 0 :(得分:7)

[:alpha:]没有您想要的特殊含义;相反,它最终只是意味着"任何字符:ahlp"。因此dfhidbuffon包含您的模式匹配(即hidbuffon),而dfdidbuffon则不包含。 (请注意,matcher.find()会在字符串中查找匹配;如果要专门匹配整个字符串,则应使用matcher.matches(),或者您可以修改模式以使用^$等锚点。)

您可能会想到许多正则表达式实现中的符号,其中[:alpha:]表示"任何字母字符&#34 ;;但首先,Java的Pattern课程并不支持这种表示法(将ajb标记为提示),其次,这些语言需要[:alpha:]里面出现一个字符类,例如为[[:alpha:]]。如果您只想匹配ASCII字母,则Java等效项为\p{Alpha}[A-Za-z];如果要匹配任何Unicode字母,则为\p{IsAlphabetic}

答案 1 :(得分:1)

:Alpha:是字母字符的Posix字符类的简写。

根据Java 7 "Pattern" docs,使用\p{Alpha}格式支持Posix字符类,而不是:alpha:格式 - 后一种格式未在参考文献中的任何位置列出。

对于我来说,使用支持的Posix字符类定义格式的模式定义可以正常工作,如下所示:

String pattern = "(\\p{Alpha})[a-zA-Z_]{7,29}";

答案 2 :(得分:0)

根据Regexpal.com“([:alpha:])”匹配“任何字符”:','a','h','l','p'“。 “dfdidbuffon”确实包含任何这些字符,因此它失败(永远不会到达[A-z]部分)。

您可能打算"[a-zA-Z](\\w){7,28}"如果直接使用正则表达式,/[a-zA-Z](\w){7,28}/

这会匹配任何'alpha'字符,然后是7到28个字符(字母数字+下划线)

如果您不想要数字,请"[a-zA-Z]([a-zA-Z_]){7,28}"