一般公司在开发一类对的号码时,会预留一些号码给以后升级的会员使用,比如旺旺靓号,QQ号等,采用正则表达式实现较好,通过规则引擎的后台页面做成实时可配置的也是不错的选择。
一. 一般会有如下的正则需求
代码中每行都标有注释,这个就是需求,为设置靓号应该考虑的方面,这里特别提示下,不能忘记跟公司相关的业务,股票代码等检查。
代码如下:
- publicclassCreditCodeRegexValidateStategyServiceImplimplementsCreditCodeValidateStategyService{
- privatestaticList<String>levitPatterns;
- staticsynchronizedprivatevoidinit(){
- if(levitPatterns==null){
- levitPatterns=newArrayList<String>();
- }else{
- return;
- }
- levitPatterns.add("^(0|13|15|18|168|400|800)[0-9]*$");
- levitPatterns.add("^d{2}(0[1-9]|1[0-2])(0[1-9]|[12][0-9]|3[01])$");
- levitPatterns.add("^d*(1688|2688|2088|2008|5188|10010|10001|666|888|668|686|688|866|868|886|999)d*$");
- levitPatterns.add("^(<a>d)(d)(d)123$");
- </a>levitPatterns.add("^(d)(d)(d)321$");
- levitPatterns.add("^d*(d)1(d)2d*$");
- levitPatterns.add("^d*(d)11(d)22d*$");
- levitPatterns.add("^(d)(d)121212$");
- levitPatterns.add("^(d)(d)(d)123$");
- levitPatterns.add("^(d)(d)2122$");
- levitPatterns.add("^(d)1(d)112$");
- levitPatterns.add("^d*(d)1{2,}d*$");
- levitPatterns.add("(?:(?:0(?=1)|1(?=2)|2(?=3)|3(?=4)|4(?=5)|5(?=6)|6(?=7)|7(?=8)|8(?=9)|9(?=0)){2,}|(?:0(?=9)|9(?=8)|8(?=7)|7(?=6)|6(?=5)|5(?=4)|4(?=3)|3(?=2)|2(?=1)|1(?=0)){2,})d");
- levitPatterns.add("^[0-9]*(518|918)$");
- }
- @Override
- publicbooleanisAllow(Stringinput){
- Assert.notNull(input);
- return!RegexUtil.contains(input,levitPatterns);
- }
- static{
- init();
- }
public class CreditCodeRegexValidateStategyServiceImpl implements CreditCodeValidateStategyService {
private static List<String> levitPatterns;
static synchronized private void init() {
if (levitPatterns == null) {
levitPatterns = new ArrayList<String>();
} else {
return;
}
// 手机号、生日号、跟公司业务相关的号码
levitPatterns.add("^(0|13|15|18|168|400|800)[0-9]*$");
levitPatterns.add("^d{2}(0[1-9]|1[0-2])(0[1-9]|[12][0-9]|3[01])$");
levitPatterns.add("^d*(1688|2688|2088|2008|5188|10010|10001|666|888|668|686|688|866|868|886|999)d*$");
// 重复号码,镜子号码
levitPatterns.add("^(<a>d)(d)(d)123$");
</a> levitPatterns.add("^(d)(d)(d)321$");
// AABB
levitPatterns.add("^d*(d)1(d)2d*$");
// AAABBB
levitPatterns.add("^d*(d)11(d)22d*$");
// ABABAB
levitPatterns.add("^(d)(d)121212$");
// ABCABC
levitPatterns.add("^(d)(d)(d)123$");
// ABBABB
levitPatterns.add("^(d)(d)2122$");
// AABAAB
levitPatterns.add("^(d)1(d)112$");
// 4-8 位置重复
levitPatterns.add("^d*(d)1{2,}d*$");
// 4位以上 位递增或者递减(7890也是递增)
levitPatterns.add("(?:(?:0(?=1)|1(?=2)|2(?=3)|3(?=4)|4(?=5)|5(?=6)|6(?=7)|7(?=8)|8(?=9)|9(?=0)){2,})d");
// 不能以 518 、918 结尾
levitPatterns.add("^[0-9]*(518|918)$");
}
@Override
public boolean isAllow(String input) {
Assert.notNull(input);
return !RegexUtil.contains(input,levitPatterns);
}
static {
init();
}
对于以上正则,前面的大多人都很熟悉了,这里主要讲位置查找和前后向查找,即如下两种号码的判断
- levitPatterns.add("^(d)(d)2122$");
// ABBABB
levitPatterns.add("^(d)(d)2122$");
- levitPatterns.add("(?:(?:0(?=1)|1(?=2)|2(?=3)|3(?=4)|4(?=5)|5(?=6)|6(?=7)|7(?=8)|8(?=9)|9(?=0)){2,})d");
// 4位以上 位递增或者递减(7890也是递增)
levitPatterns.add("(?:(?:0(?=1)|1(?=2)|2(?=3)|3(?=4)|4(?=5)|5(?=6)|6(?=7)|7(?=8)|8(?=9)|9(?=0)){2,})d");
位置查找:2122 这部分代表的 第一个A 位置是1 第二个B位置是2,重复B则用2标识
后向查找 ("(?:(?:0(?=1)| 对于连续号码,?=表示往后看,要判断0后面是1吗,1后面是2吗,如此反复可以得到连续号码
二. 使用 org.apache.oro.text.regex.Pattern 代替 java自身带的partern,
为什么抛弃java现有的API不用,而使用perl5规范的正则库呢?他是最全面的正则表达式API,全面兼容perl5,同时也是优化的最好的API之一,在未来的JDK版本中可能会看到的。
上面程序调用的正则代码如下:
- publicclassRegexUtil{
- privatestaticPatternCompilercompiler=newPerl5Compiler();
- privatestaticPatternMatchermatcher=newPerl5Matcher();
- privatestaticPatternpattern=null;
- publicstaticbooleancontains(Stringinput,StringpatternString){
- try{
- pattern=compiler.compile(patternString);
- if(matcher.contains(input,pattern)){
- returntrue;
- }
- }catch(MalformedPatternExceptione){
- returnfalse;
- }
- returnfalse;
- }
- publicstaticbooleancontains(Stringinput,List<String>patternStrings){
- for(Iterator<String>lt=patternStrings.listIterator();lt.hasNext();){
- if(contains(input,(String)lt.next())){
- returntrue;
- }
- continue;
- }
- returnfalse;
- }
- }