Java正则表达式判断变量名是否合法(字母、数字和下划线的组合),手机号匹配、判断字符串是否有中文,判断字符串是否是数,判断字符串是否正整数

 校验identifier是否是下划线、字母、数字组合而成,最少是一个字符,最大64个字符;

+标识前面的规则出现一次或者多次!!!

@ApiModelProperty("变量识符")
@Pattern(regexp = "^[_a-zA-Z0-9]+$", message = "标识符不合法")
private String identifier
    public boolean isValidNaming() {
        String name = "_uhhaa";
        String regx = "^[_a-zA-Z0-9]+$";
        Pattern pattern = Pattern.compile(regx);
        Matcher matcher = pattern.matcher(name);
        // 匹配则返回 true 否则 false
        System.out.println(matcher.find());
        return matcher.find();
    }
    /**
	 * 手机号码验证
	 * 
	 * @param sjhm
	 * @return
	 */
	public static boolean isMobile(String sjhm) {
		boolean boo = false;
		try {
			if (isEmpty(sjhm)) {
				return false;
			}
			Pattern ptn = Pattern.compile("^[1][3,4,5,6,7,8,9][0-9]{9}+&;);
			Matcher mcr = ptn.matcher(sjhm);
			boo = mcr.matches();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return boo;
	}

    /**
	 * 
	 * 判断字符串是否是数
	 *
	 * @param str
	 * @return
	 */
	public static boolean isDigit(String str) {
		String reg = "\\d+\\.{0,1}\\d*";
		return str.matches(reg);
	}

	// 判断字符串是否含有中文
	public static Boolean isChCode(String str) {
		
		String regEx = "[\\u4e00-\\u9fa5]";
		Pattern p = Pattern.compile(regEx);
		Matcher m = p.matcher(str);

		return m.find();
	}
// 判断字符串是否是正整数
public static boolean checkIsNum(String value) {
		if (StringUtils.isNotEmpty(value)) {
			return value.matches("^[1-9]+[0-9]*);
		}
		return false;
	}

其他知识

java.util.regex

在regex包中,包括了两个类,Pattern(模式类)和Matcher(匹配器类)。Pattern类是用来表达和陈述所要搜索模式的对象,Matcher类是真正影响搜索的对象。另加一个新的例外类,PatternSyntaxException,当遇到不合法的搜索模式时,会抛出例外。

Pattern

  • 简介
    正则表达式的编译表示形式。

    指定为字符串的正则表达式必须首先被编译为此类的实例。然后,可将得到的模式用于创建 Matcher 对象,依照正则表达式,该对象可以与任意字符序列匹配。执行匹配所涉及的所有状态都驻留在匹配器中,所以多个匹配器可以共享同一模式。

    因此,典型的调用顺序是

     Pattern p = Pattern.compile("a*b");
     Matcher m = p.matcher("aaaaab");
     boolean b = m.matches();
    

    在仅使用一次正则表达式时,可以方便地通过此类定义 matches 方法。此方法编译表达式并在单个调用中将输入序列与其匹配。语句

     boolean b = Pattern.matches("a*b", "aaaaab");
    

    等效于上面的三个语句,尽管对于重复的匹配而言它效率不高,因为它不允许重用已编译的模式。
    此类的实例是不可变的,可供多个并发线程安全使用。Matcher 类的实例用于此目的则不安全。

  • 常用方法

Pattern类中最重要的方法便是compilematcher,上面已经给出示例。下面看看其他方法:

方法返回类型功能示例
flags()int返回此模式的匹配标志。Pattern.compile("\\w*", Pattern.MULTILINE).flags() => 8
pattern()String返回在其中编译过此模式的正则表达式。Pattern.compile("\\w*").pattern() => \w*
static quote(String s)String返回指定 String 的字面值模式 String。Pattern.quote("\\w+") => \Q\w+\E

Matcher

  • 简介

通过解释 Pattern 对 character sequence 执行匹配操作的引擎。

通过调用模式的 matcher 方法从模式创建匹配器。创建匹配器后,可以使用它执行三种不同的匹配操作:

  • matches 方法尝试将整个输入序列与该模式匹配。

  • lookingAt 尝试将输入序列从头开始与该模式匹配。

  • find 方法扫描输入序列以查找与该模式匹配的下一个子序列。

每个方法都返回一个表示成功或失败的布尔值。通过查询匹配器的状态可以获取关于成功匹配的更多信息。

匹配器在其输入的子集(称为区域)中查找匹配项。默认情况下,此区域包含全部的匹配器输入。可通过 region 方法修改区域,通过 regionStart 和 regionEnd 方法查询区域。区域边界与某些模式构造交互的方式是可以更改的。

此类还定义使用新字符串替换匹配子序列的方法,需要时,可以从匹配结果计算出新字符串的内容。可以先后使用 appendReplacement 和 appendTail 方法将结果收集到现有的字符串缓冲区,或者使用更加便捷的 replaceAll 方法创建一个可以在其中替换输入序列中每个匹配子序列的字符串。

匹配器的显式状态包括最近成功匹配的开始和结束索引。它还包括模式中每个捕获组捕获的输入子序列的开始和结束索引以及该子序列的总数。出于方便的考虑,还提供了以字符串的形式返回这些已捕获子序列的方法。

匹配器的显式状态最初是未定义的;在成功匹配导致 IllegalStateException 抛出之前尝试查询其中的任何部分。每个匹配操作都将重新计算匹配器的显式状态。

匹配器的隐式状态包括输入字符序列和添加位置,添加位置最初是零,然后由 appendReplacement 方法更新。

可以通过调用匹配器的 reset() 方法来显式重置匹配器,如果需要新输入序列,则调用其 reset(CharSequence) 方法。重置匹配器将放弃其显式状态信息并将添加位置设置为零。

此类的实例用于多个并发线程是不安全的。

  • 常用方法

matches()
表示字符串完全符合给出的正则表达式所表示的范围。只要有一个字符不匹配则返回false。如:

Pattern.matches("[a-z]", "aAbBcC")

返回false,因为正则表达式表示的范围不包含大写字母。

find()
find()尝试查找与该模式匹配的输入序列的下一个子序列。
此方法从匹配器区域的开头开始,如果该方法的前一次调用成功了并且从那时开始匹配器没有被重置,则从以前匹配操作没有匹配的第一个字符开始。
如果匹配成功,则可以通过 start、end 和 group 方法获取更多信息。

	Pattern pattern = Pattern.compile("[a-z]");
	Matcher matcher = pattern.matcher("aAbBcC");
	matcher.find();

返回true,因为可以匹配到小写字母。

需要注意的是在执行find()方法时,其内部指针会跟着变动,比如第一次调用完毕,此时的matcher.start()为0,因为第一个字母就匹配上了,而matcher.end()则返回2,因为它返回的是最后不匹配(A)的位置的下一个索引,因此可以通过如下方法看到指针移动轨迹:

        Pattern p = Pattern.compile("\\d{3,5}");
        String s = "123-34345-234-00";
        while (m.find()) {
            System.out.println(m.start() + "-" + m.end());
        }

打印结果:

可以看到,find方法比较实诚,善始善终,但我们有时候需要人工插手而不总是从头到尾来一遍,这就涉及到find方法的另一个多态形式了。

find(int start)
从指定位置开始匹配,使用此方法模拟find():

        int index = 0;
        while (m.find(index)) {
            System.out.println(m.start() + "-" + m.end());
            index = m.end();
        }

lookingAt()
此方法总是从头开始匹配,无论是否匹配上均立即返回相应结果,并且不再继续匹配,语言乏力,此处使用find方法模拟:

    public static void main(String[] args) throws Exception {
        Pattern p = Pattern.compile("\\d{3,5}");
        String s = "123-34345-234-00";
        Matcher m = p.matcher(s);

        System.out.println(cosplayMethodLookingAt(m));
        System.out.println(cosplayMethodLookingAt(m));
        System.out.println(cosplayMethodLookingAt(m));
        System.out.println(cosplayMethodLookingAt(m));
    }

    private static boolean cosplayMethodLookingAt(Matcher m) {
        boolean res = m.find() && m.start() == 0;
        m.reset();
        return res;
    }

显示效果与lookingAt方法相同,但内部实现不一样:

    public static void main(String[] args) throws Exception {
        Pattern p = Pattern.compile("\\d{3,5}");
        String s = "123-34345-234-00";
        Matcher m = p.matcher(s);

        m.find();
        m.lookingAt();
        m.find();
        // 4
        System.out.println(m.start());
        cosplayMethodLookingAt(m);
        m.find();
        System.out.println(m.start());
    }

    private static boolean cosplayMethodLookingAt(Matcher m) {
        boolean res = m.find() && m.start() == 0;
        m.reset();
        return res;
    }

打印结果:

由此可见,lookingAt方法并不会重置匹配使用的内部指针。

appendReplacement
public Matcher appendReplacement(StringBuffer sb, String replacement)

实现非终端添加和替换步骤。
此方法执行以下操作:

它从添加位置开始在输入序列读取字符,并将其添加到给定字符串缓冲区。在读取以前匹配之前的最后字符(即位于索引 start() - 1 处的字符)之后,它就会停止。

它将给定替换字符串添加到字符串缓冲区。

它将此匹配器的添加位置设置为最后匹配位置的索引加 1,即 end()。

替换字符串可能包含到以前匹配期间所捕获的子序列的引用:g每次出现时,都将被group(g)的计算结果替换。g每次出现时,都将被group(g)的计算结果替换。 之后的第一个数始终被视为组引用的一部分。如果后续的数可以形成合法组引用,则将被合并到 g 中。只有数字 '0' 到 '9' 被视为组引用的可能组件。例如,如果第二个组匹配字符串 "foo",则传递替换字符串 "2bar"将导致"foobar"被添加到字符串缓冲区。可能将美元符号(2bar"将导致"foobar"被添加到字符串缓冲区。可能将美元符号() 作为替换字符串中的字面值(通过前面使用一个反斜线 ($))包括进来。

注意,在替换字符串中使用反斜线 () 和美元符号 ($) 可能导致与作为字面值替换字符串时所产生的结果不同。美元符号可视为到如上所述已捕获子序列的引用,反斜线可用于转义替换字符串中的字面值字符。

此方法设计用于循环以及 appendTail 和 find 方法中。例如,以下代码将 one dog two dogs in the yard 写入标准输出流中:

 Pattern p = Pattern.compile("cat");
 Matcher m = p.matcher("one cat two cats in the yard");
 StringBuffer sb = new StringBuffer();
 while (m.find()) {
     m.appendReplacement(sb, "dog");
 }
 m.appendTail(sb);
 System.out.println(sb.toString());

输出结果:

appendTail

StringBuffer appendTail(StringBuffer sb)
此方法从添加位置开始从输入序列读取字符,并将其添加到给定字符串缓冲区。可以在一次或多次调用 appendReplacement 方法后调用它来复制剩余的输入序列。

以上例来说,当匹配到第二个cat时,while语句块中的代码就失效了,此时后面的字符串s in the yard就需要使用appendTail方法来补齐,否则输出结果就是:

显然有所缺失。

group

String group()
返回由以前匹配操作所匹配的输入子序列。
对于具有输入序列 s 的匹配器 m,表达式 m.group() 和 s.substring(m.start(), m.end()) 是等效的。
注意,某些模式(例如,a*)匹配空字符串。当模式成功匹配输入中的空字符串时,此方法将返回空字符串。

group(int group)

String group(int group)
返回在以前匹配操作期间由给定组捕获的输入子序列。
对于匹配器 m、输入序列 s 和组索引 g,表达式 m.group(g) 和 s.substring(m.start(g), m.end(g)) 是等效的。

捕获组是从 1 开始从左到右的索引。组零表示整个模式,因此表达式 m.group(0) 等效于 m.group()。

如果该匹配成功了,但指定组未能匹配输入序列的任何部分,则返回 null。注意,某些组(例如,(a*))匹配空字符串。当这些的组成功匹配输入中的空字符串时,此方法将返回空字符串。

        Pattern p = Pattern.compile("\\b\\w+(o\\w+)\\b");
        Matcher m = p.matcher("i love you");
        while (m.find()) {
            System.out.println("整个匹配结果=>"+m.group());
            System.out.println("一组匹配结果=>"+m.group(1));
        }

输出结果:

其他

其他方法要么可以融会贯通,比如start(int),要么就是不常用,比如hasAnchoringBounds(),因此在需要的时候可以查看中文文档。
奉上连接:Matcher

常用正则

校验数字的表达式

数字:^[0-9]*$
n位的数字:^\d{n}$
至少n位的数字:^\d{n,}$
m-n位的数字:^\d{m,n}$
零和非零开头的数字:^(0|[1-9][0-9]*)$
非零开头的最多带两位小数的数字:^([1-9][0-9]*)+(.[0-9]{1,2})?$
带1-2位小数的正数或负数:^(\-)?\d+(\.\d{1,2})?$
正数、负数、和小数:^(\-|\+)?\d+(\.\d+)?$
有两位小数的正实数:^[0-9]+(.[0-9]{2})?$
有1~3位小数的正实数:^[0-9]+(.[0-9]{1,3})?$
非零的正整数:^[1-9]\d*$ 或 ^([1-9][0-9]*){1,3}$ 或 ^\+?[1-9][0-9]*$
非零的负整数:^\-[1-9][]0-9″*$ 或 ^-[1-9]\d*$
非负整数:^\d+$ 或 ^[1-9]\d*|0$
非正整数:^-[1-9]\d*|0$ 或 ^((-\d+)|(0+))$
非负浮点数:^\d+(\.\d+)?$ 或 ^[1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0$
非正浮点数:^((-\d+(\.\d+)?)|(0+(\.0+)?))$ 或 ^(-([1-9]\d*\.\d*|0\.\d*[1-9]\d*))|0?\.0+|0$
正浮点数:^[1-9]\d*\.\d*|0\.\d*[1-9]\d*$ 或 ^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$
负浮点数:^-([1-9]\d*\.\d*|0\.\d*[1-9]\d*)$ 或 ^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$
浮点数:^(-?\d+)(\.\d+)?$ 或 ^-?([1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0)$

校验字符的表达式

汉字:^[\u4e00-\u9fa5]{0,}$
英文和数字:^[A-Za-z0-9]+$ 或 ^[A-Za-z0-9]{4,40}$
长度为3-20的所有字符:^.{3,20}$
由26个英文字母组成的字符串:^[A-Za-z]+$
由26个大写英文字母组成的字符串:^[A-Z]+$
由26个小写英文字母组成的字符串:^[a-z]+$
由数字和26个英文字母组成的字符串:^[A-Za-z0-9]+$
由数字、26个英文字母或者下划线组成的字符串:^\w+$ 或 ^\w{3,20}$
中文、英文、数字包括下划线:^[\u4E00-\u9FA5A-Za-z0-9_]+$
中文、英文、数字但不包括下划线等符号:^[\u4E00-\u9FA5A-Za-z0-9]+$ 或 ^[\u4E00-\u9FA5A-Za-z0-9]{2,20}$
可以输入含有^%&',;=?$\”等字符:[^%&',;=?$\x22]+
禁止输入含有~的字符:[^~\x22]+

特殊需求表达式

Email地址:^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$
域名:[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(/.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+/.?
InternetURL:[a-zA-z]+://[^\s]* 或 ^http://([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$
手机号码:^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\d{8}$
电话号码(“XXX-XXXXXXX”、”XXXX-XXXXXXXX”、”XXX-XXXXXXX”、”XXX-XXXXXXXX”、”XXXXXXX”和”XXXXXXXX):^($$\d{3,4}-)|\d{3.4}-)?\d{7,8}$
国内电话号码(0511-4405222、021-87888822):\d{3}-\d{8}|\d{4}-\d{7}
身份证号(15位、18位数字):^\d{15}|\d{18}$
短身份证号码(数字、字母x结尾):^([0-9]){7,18}(x|X)?$ 或 ^\d{8,18}|[0-9x]{8,18}|[0-9X]{8,18}?$
帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线):^[a-zA-Z][a-zA-Z0-9_]{4,15}$
密码(以字母开头,长度在6~18之间,只能包含字母、数字和下划线):^[a-zA-Z]\w{5,17}$
强密码(必须包含大小写字母和数字的组合,不能使用特殊字符,长度在8-10之间):^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,10}$
日期格式:^\d{4}-\d{1,2}-\d{1,2}
一年的12个月(01~09和1~12):^(0?[1-9]|1[0-2])$
一个月的31天(01~09和1~31):^((0?[1-9])|((1|2)[0-9])|30|31)$

xml文件:^([a-zA-Z]+-?)+[a-zA-Z0-9]+\\.[x|X][m|M][l|L]$
中文字符的正则表达式:[\u4e00-\u9fa5]
双字节字符:[^\x00-\xff] (包括汉字在内,可以用来计算字符串的长度(一个双字节字符长度计2,ASCII字符计1))
空白行的正则表达式:\n\s*\r (可以用来删除空白行)
HTML标记的正则表达式:<(\S*?)[^>]*>.*?</\1>|<.*? /> (网上流传的版本太糟糕,上面这个也仅仅能部分,对于复杂的嵌套标记依旧无能为力)
首尾空白字符的正则表达式:^\s*|\s*$(^\s*)|(\s*$) (可以用来删除行首行尾的空白字符(包括空格、制表符、换页符等等),非常有用的表达式)
腾讯QQ号:[1-9][0-9]{4,} (腾讯QQ号从10000开始)
中国邮政编码:[1-9]\d{5}(?!\d) (中国邮政编码为6位数字)
IP地址:\d+\.\d+\.\d+\.\d+ (提取IP地址时有用)
IP地址:((25[0-5]|2[0-4]\d|((1\d{2})|([1-9]?\d)))\.){3}\2

钱的输入格式

有四种钱的表示形式我们可以接受:”10000.00″ 和 “10,000.00″, 和没有 “分” 的 “10000″ 和 “10,000″:^[1-9][0-9]*$
这表示任意一个不以0开头的数字,但是,这也意味着一个字符”0″不通过,所以我们采用下面的形式:^(0|[1-9][0-9]*)$
一个0或者一个不以0开头的数字.我们还可以允许开头有一个负号:^(0|-?[1-9][0-9]*)$
这表示一个0或者一个可能为负的开头不为0的数字.让用户以0开头好了.把负号的也去掉,因为钱总不能是负的吧.下面我们要加的是说明可能的小数部分:^[0-9]+(.[0-9]+)?$
必须说明的是,小数点后面至少应该有1位数,所以”10.”是不通过的,但是 “10″ 和 “10.2″ 是通过的:^[0-9]+(.[0-9]{2})?$
这样我们规定小数点后面必须有两位,如果你认为太苛刻了,可以这样:^[0-9]+(.[0-9]{1,2})?$
这样就允许用户只写一位小数。下面我们该考虑数字中的逗号了,我们可以这样:^[0-9]{1,3}(,[0-9]{3})*(.[0-9]{1,2})?$
1到3个数字,后面跟着任意个 逗号+3个数字,逗号成为可选,而不是必须:^([0-9]+|[0-9]{1,3}(,[0-9]{3})*)(.[0-9]{1,2})?$
备注:这就是最终结果了,别忘了”+”可以用”*”替代。如果你觉得空字符串也可以接受的话(奇怪,为什么?)最后,别忘了在用函数时去掉去掉那个反斜杠,一般的错误都在这里

 参考这篇文章

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值