^ [A-Z](([A-Z_0-9])* [^ _])?$错误匹配

时间:2016-11-15 21:40:23

标签: java regex regex-negation

需要Java泛型类型参数的正则表达式,所以我尝试过:

^[A-Z](([A-Z_0-9])*[^_])?$

表示类型名称应该包含1个或更多字符,全部大写和数字,这可能是
使用'_'作为分隔符,但不是最后,f.e。 'TT_A9'
但令我惊讶的是,我的正则表达式工具显示“Aa”或“AAa”或“AA-”的匹配 我写了一个简单的测试类来检查:

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class RegexTestPatternMatcher { 

public static final String test = "AA-";

public static void main(String[] args) {
   Pattern pattern = Pattern.compile("^[A-Z](([A-Z_0-9])*[^_])?$");
   Matcher matcher = pattern.matcher(test);
   System.out.println("Matches ? " + matcher.matches());
  }
}

输出:

AA- Matches ? true

对于AAa也是如此,但AA_的情况也是如此 如果我使用正则表达式^[A-Z](([A-Z_0-9])*[^_a-z-])?$,它可以工作 但我不明白为什么我需要使用'a-z'和' - '作为排除,
当我只是在寻找大写字符时!?

1 个答案:

答案 0 :(得分:2)

使用negated character class时 - 与原始模式[^_]一样 - 你告诉正则表达式使用的不是类中定义的字符。因此,你的正则表达式实际上至少需要2个字符,第一个是大写的ASCII字母,最后是_的任何字符,而_中可以有任何字符,{{1 }和0-9介于两者之间。

您正在寻找锚定在字符串末尾的negative lookbehind

A-Z

请参阅regex demo

^[A-Z][A-Z_0-9]*$(?<!_) ^^^^^^ 位于字符串末尾的所有匹配都将失败。 _未被消耗,仅检查是否存在,因此模式将接受(匹配)以大写ASCII字母开头的1-char字符串,并且可选地跟随{中定义的范围中的字符{1}}字符类。

我还建议删除所有冗余分组(无论如何你都没有使用捕获的子文件)。