Java基础:正则表达式

相关阅读

  1. Java基础:String类
  2. Java字符串格式化
  3. Java基础:正则表达式

1. 正则表达式概述

正则表达式,又称正规表示法、常规表示法(英语:Regular Expression,在代码中常简写为regex、regexp或RE),计算机科学的一个概念。正则表达式使用单个字符串来描述、匹配一系列符合某个句法规则的字符串。在很多文本编辑器里,正则表达式通常被用来检索、替换那些符合某个模式的文本

许多程序设计语言都支持利用正则表达式进行字符串操作。例如,在Perl中就内建了一个功能强大的正则表达式引擎。正则表达式这个概念最初是由Unix中的工具软件(例如sed和grep)普及开的。正则表达式通常缩写成“regex”,单数有regexp、regex,复数有regexps、regexes、regexen

正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑

1.1 给定一个正则表达式和另一个字符串,我们可以达到如下的目的

  • 给定的字符串是否符合正则表达式的过滤逻辑(称作“匹配”)
  • 可以通过正则表达式,从字符串中获取我们想要的特定部分

1.2 正则表达式的特点是

  • 灵活性、逻辑性和功能性非常的强;
  • 可以迅速地用极简单的方式达到字符串的复杂控制。
  • 对于刚接触的人来说,比较晦涩难懂。

由于正则表达式主要应用对象是文本,因此它在各种文本编辑器场合都有应用,小到著名编辑器EditPlus,大到Microsoft Word、Visual Studio等大型编辑器,都可以使用正则表达式来处理文本内容

2. 正则表达式基础知识

2.1 规则字符在java.util.regex Pattern类中

2.2 常见符号

2.2.1 字符

符号 说明
X 字符X
\\ 反斜线
\t 制表符 ('\u0009')
\n 回车
\r 换行
\f 换页符 ('\u000C')
\a 报警 (bell) 符 ('\u0007')

2.2.2 字符类

符号 说明
[abc] a、b或c
[^abc] 任何字符,除了a、b或c
[a-zA-Z] a到z,或A到Z
[0-9] 0到9的字符
[a-d[m-p]] a到 d或 m 到 p:[a-dm-p](并集)
[a-z&&[def]] d、e或 f(交集)
[a-z&&[^bc]] a到 z,除了 b和 c:[ad-z](减去)
[a-z&&[^m-p]] a到 z,而非 m到 p:[a-lq-z](减去)

2.2.3 预定义字符

符号 说明
. 任何字符
\d 数字:[0-9]
\D 非数字: [^0-9]
\s 空白字符:[ \t\n\x0B\f\r]
\S 非空白字符:[^\s]
\w 单词字符:[a-zA-Z_0-9]
\W 非单词字符:[^\w]

2.3 边界匹配器

符号 说明
^ 行开头
$ 行结尾
\b 单词边界
\B 非单词边界
\A 输入的开头
\G 上一个匹配的结尾
\Z 输入的结尾,仅用于最后的结束符(如果有的话)
\z 输入的结尾

2.3.1 Greedy数量词

符号 说明
X? 0次或1次
X* 0次以上
X+ 1次以上
X{n} 恰好n次
X{n,} 至少n次
X{n,m} n-m次

2.3.2 组和捕获

捕获组可以通过从左到右计算其开括号来编号。例如,在表达式 ((A)(B(C)))中,存在四个这样的组:

  • ((A)(B(C)))
  • \A
  • (B(C))
  • (C)

组零始终代表整个表达式。在替换中常用$匹配组的内容。

3. 正则表达式的应用

3.1 判断功能

public  boolean matches(String regex):编译给定正则表达式并尝试将给定输入与其匹配。

3.2 分割功能

 public  String[] split(String regex):根据指定的正则表达式分割字符串

3.3 替换功能

public  String replaceAll(String regex,String replacement)

使用给定的 replacement 替换此字符串所有匹配给定的正则表达式的子字符串。

3.4 获取功能

Pattern和Matcher类的使用

package cn.itcast_05;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/*
 * 获取功能
 *      Pattern和Matcher类的使用
 *      
 *      模式和匹配器的基本使用顺序
 */
public class RegexDemo {
    public static void main(String[] args) {
        // 模式和匹配器的典型调用顺序
        // 把正则表达式编译成模式对象
        Pattern p = Pattern.compile("a*b");
        // 通过模式对象得到匹配器对象,这个时候需要的是被匹配的字符串
        Matcher m = p.matcher("aaaaab");
        // 调用匹配器对象的功能
        boolean b = m.matches();
        System.out.println(b);
        
        //这个是判断功能,但是如果做判断,这样做就有点麻烦了,我们直接用字符串的方法做
        String s = "aaaaab";
        String regex = "a*b";
        boolean bb = s.matches(regex);
        System.out.println(bb);
    }
}

Pattern 匹配模式

方法声明 功能描述
compile() 把正则表达式编译成匹配模式
matcher() 根据匹配模式去匹配指定的字符串,得到匹配器

Matcher 匹配器

方法声明 功能描述
matches() 匹配字符串
find() 查找有没有满足条件的子串
group() 获取满足条件的子串

3.4 注意事项

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

4. 正则表达式的练习

4.1 判断功能:校验邮箱

package cn.itcast_02;
import java.util.Scanner;
/*
 * 校验邮箱
 * 
 * 分析:
 *      A:键盘录入邮箱
 *      B:定义邮箱的规则
 *          1517806580@qq.com
 *          liuyi@163.com
 *          linqingxia@126.com
 *          fengqingyang@sina.com.cn
 *          fqy@itcast.cn
 *      C:调用功能,判断即可
 *      D:输出结果
 */
public class RegexTest {
    public static void main(String[] args) {
        //键盘录入邮箱
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入邮箱:");
        String email = sc.nextLine();
        
        //定义邮箱的规则
        //String regex = "[a-zA-Z_0-9]+@[a-zA-Z_0-9]{2,6}(\\.[a-zA-Z_0-9]{2,3})+";
        String regex = "\\w+@\\w{2,6}(\\.\\w{2,3})+";
        
        //调用功能,判断即可
        boolean flag = email.matches(regex);
        
        //输出结果
        System.out.println("flag:"+flag);
    }
}

4.2 分割功能

代码示例:我有如下一个字符串:”91 27 46 3850”,请写代码实现最终输出结果是:”27 3846 50 91”

package cn.itcast_03;
import java.util.Arrays;
/*
 * 我有如下一个字符串:"91 27 46 38 50"
 * 请写代码实现最终输出结果是:"27 38 46 50 91"
 * 
 * 分析:
 *      A:定义一个字符串
 *      B:把字符串进行分割,得到一个字符串数组
 *      C:把字符串数组变换成int数组
 *      D:对int数组排序
 *      E:把排序后的int数组在组装成一个字符串
 *      F:输出字符串
 */
public class RegexTest {
    public static void main(String[] args) {
        // 定义一个字符串
        String s = "91 27 46 38 50";

        // 把字符串进行分割,得到一个字符串数组
        String[] strArray = s.split(" ");

        // 把字符串数组变换成int数组
        int[] arr = new int[strArray.length];

        for (int x = 0; x < arr.length; x++) {
            arr[x] = Integer.parseInt(strArray[x]);
        }

        // 对int数组排序
        Arrays.sort(arr);

        // 把排序后的int数组在组装成一个字符串
        StringBuilder sb = new StringBuilder();
        for (int x = 0; x < arr.length; x++) {
            sb.append(arr[x]).append(" ");
        }
        //转化为字符串
        String result = sb.toString().trim();
        
        //输出字符串
        System.out.println("result:"+result);
    }
}

4.3 替换功能:论坛中不能出现数字字符,用替换*

package cn.itcast_04;
/*
 * 替换功能
 *      String类的public String replaceAll(String regex,String replacement)
 *      使用给定的 replacement 替换此字符串所有匹配给定的正则表达式的子字符串。 
 */
public class RegexDemo {
    public static void main(String[] args) {
        // 定义一个字符串
        String s = "helloqq12345worldkh622112345678java";

        // 我要去除所有的数字,用*给替换掉
        // String regex = "\\d+";
        // String regex = "\\d";
        //String ss = "*";
        
        
        // 直接把数字干掉
        String regex = "\\d+";
        String ss = "";

        String result = s.replaceAll(regex, ss);
        System.out.println(result);
    }
}

4.4 获取功能:获取由三个字符组成的单词

package cn.itcast_05;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/*
 * 获取功能:
 * 获取下面这个字符串中由三个字符组成的单词
 * da jia ting wo shuo,jin tian yao xia yu,bu shang wan zi xi,gao xing bu?
 */
public class RegexDemo2 {
    public static void main(String[] args) {
        // 定义字符串
        String s = "da jia ting wo shuo,jin tian yao xia yu,bu shang wan zi xi,gao xing bu?";
        // 规则
        String regex = "\\b\\w{3}\\b";

        // 把规则编译成模式对象
        Pattern p = Pattern.compile(regex);
        // 通过模式对象得到匹配器对象
        Matcher m = p.matcher(s);
        // 调用匹配器对象的功能
        // 通过find方法就是查找有没有满足条件的子串
        // public boolean find()
        // boolean flag = m.find();
        // System.out.println(flag);
        // // 如何得到值呢?
        // // public String group()
        // String ss = m.group();
        // System.out.println(ss);
        //
        // // 再来一次
        // flag = m.find();
        // System.out.println(flag);
        // ss = m.group();
        // System.out.println(ss);

        while (m.find()) {
            System.out.println(m.group());
        }

        // 注意:一定要先find(),然后才能group()
        // IllegalStateException: No match found
        // String ss = m.group();
        // System.out.println(ss);
    }
}

5. 正则表达式工具类

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

/**
 * 正则工具类 提供验证邮箱、手机号、电话号码、身份证号码、数字等方法
 */
public final class RegexUtils {

    /**
     * 验证Email
     * 
     * @param email
     *            email地址,格式:zhangsan@sina.com,zhangsan@xxx.com.cn,xxx代表邮件服务商
     * @return 验证成功返回true,验证失败返回false ^ :匹配输入的开始位置。 \:将下一个字符标记为特殊字符或字面值。
     *         :匹配前一个字符零次或几次。 + :匹配前一个字符一次或多次。 (pattern) 与模式匹配并记住匹配。 x|y:匹配 x 或
     *         y。 [a-z] :表示某个范围内的字符。与指定区间内的任何字符匹配。 \w :与任何单词字符匹配,包括下划线。
     * 
     *         {n,m} 最少匹配 n 次且最多匹配 m 次 $ :匹配输入的结尾。
     */
    public static boolean checkEmail(String email) {
        String regex = "^(\\w)+(\\.\\w+)*@(\\w)+((\\.\\w{2,3}){1,3})$";
        return Pattern.matches(regex, email);
    }

    /**
     * 验证身份证号码
     * 
     * @param idCard
     *            居民身份证号码15位或18位,最后一位可能是数字或字母
     * @return 验证成功返回true,验证失败返回false
     */
    public static boolean checkIdCard(String idCard) {
        String regex = "[1-9]\\d{13,16}[a-zA-Z0-9]{1}";
        return Pattern.matches(regex, idCard);
    }

    /**
     * 验证手机号码(支持国际格式,+86135xxxx...(中国内地),+00852137xxxx...(中国香港))
     * 
     * @param mobile
     *            移动、联通、电信运营商的号码段
     *            <p>
     *            移动的号段:134(0-8)、135、136、137、138、139、147(预计用于TD上网卡)
     *            、150、151、152、157(TD专用)、158、159、187(未启用)、188(TD专用)
     *            </p>
     *            <p>
     *            联通的号段:130、131、132、155、156(世界风专用)、185(未启用)、186(3g)
     *            </p>
     *            <p>
     *            电信的号段:133、153、180(未启用)、189
     *            </p>
     *            <p>
     *            虚拟运营商的号段:170
     *            </p>
     * @return 验证成功返回true,验证失败返回false
     */
    public static boolean checkMobile(String mobile) {
        String regex = "(\\+\\d+)?1[34578]\\d{9}$";
        return Pattern.matches(regex, mobile);
    }

    /**
     * 验证固定电话号码
     * 
     * @param phone
     *            电话号码,格式:国家(地区)电话代码 + 区号(城市代码) + 电话号码,如:+8602085588447
     *            <p>
     *            <b>国家(地区) 代码 :</b>标识电话号码的国家(地区)的标准国家(地区)代码。它包含从 0 到 9
     *            的一位或多位数字, 数字之后是空格分隔的国家(地区)代码。
     *            </p>
     *            <p>
     *            <b>区号(城市代码):</b>这可能包含一个或多个从 0 到 9 的数字,地区或城市代码放在圆括号——
     *            对不使用地区或城市代码的国家(地区),则省略该组件。
     *            </p>
     *            <p>
     *            <b>电话号码:</b>这包含从 0 到 9 的一个或多个数字
     *            </p>
     * @return 验证成功返回true,验证失败返回false
     */
    public static boolean checkPhone(String phone) {
        // String regex = "(\\+\\d+)?(\\d{3,4}\\-?)?\\d{7,8}$";
        String regex = "^1\\d{10}$";
        return Pattern.matches(regex, phone);
    }

    /**
     * 验证整数(正整数和负整数)
     * 
     * @param digit
     *            一位或多位0-9之间的整数
     * @return 验证成功返回true,验证失败返回false
     */
    public static boolean checkDigit(String digit) {
        String regex = "\\-?[1-9]\\d+";
        return Pattern.matches(regex, digit);
    }

    /**
     * 验证整数和浮点数(正负整数和正负浮点数)
     * 
     * @param decimals
     *            一位或多位0-9之间的浮点数,如:1.23,233.30
     * @return 验证成功返回true,验证失败返回false
     */
    public static boolean checkDecimals(String decimals) {
        String regex = "\\-?[1-9]\\d+(\\.\\d+)?";
        return Pattern.matches(regex, decimals);
    }

    /**
     * 验证空白字符
     * 
     * @param blankSpace
     *            空白字符,包括:空格、\t、\n、\r、\f、\x0B
     * @return 验证成功返回true,验证失败返回false
     */
    public static boolean checkBlankSpace(String blankSpace) {
        String regex = "\\s+";
        return Pattern.matches(regex, blankSpace);
    }

    /**
     * 验证中文
     * 
     * @param chinese
     *            中文字符
     * @return 验证成功返回true,验证失败返回false
     */
    public static boolean checkChinese(String chinese) {
        String regex = "^[\u4E00-\u9FA5]+$";
        return Pattern.matches(regex, chinese);
    }

    /**
     * 验证日期(年月日)
     * 
     * @param birthday
     *            日期,格式:1992-09-03,或1992.09.03
     * @return 验证成功返回true,验证失败返回false
     */
    public static boolean checkBirthday(String birthday) {
        String regex = "[1-9]{4}([-./])\\d{1,2}\\1\\d{1,2}";
        return Pattern.matches(regex, birthday);
    }

    /**
     * 验证URL地址
     * 
     * @param url
     *            格式:http://blog.csdn.net:80/xyang81/article/details/7705960? 或
     *            http://www.csdn.net:80
     * @return 验证成功返回true,验证失败返回false
     */
    public static boolean checkURL(String url) {
        String regex = "(https?://(w{3}\\.)?)?\\w+\\.\\w+(\\.[a-zA-Z]+)*(:\\d{1,5})?(/\\w*)*(\\??(.+=.*)?(&.+=.*)?)?";
        return Pattern.matches(regex, url);
    }

    /**
     * 匹配中国邮政编码
     * 
     * @param postcode
     *            邮政编码
     * @return 验证成功返回true,验证失败返回false
     */
    public static boolean checkPostcode(String postcode) {
        String regex = "[1-9]\\d{5}";
        return Pattern.matches(regex, postcode);
    }

    /**
     * 匹配IP地址(简单匹配,格式,如:192.168.1.1,127.0.0.1,没有匹配IP段的大小)
     * 
     * @param ipAddress
     *            IPv4标准地址
     * @return 验证成功返回true,验证失败返回false
     */
    public static boolean checkIpAddress(String ipAddress) {
        String regex = "[1-9](\\d{1,2})?\\.(0|([1-9](\\d{1,2})?))\\.(0|([1-9](\\d{1,2})?))\\.(0|([1-9](\\d{1,2})?))";
        return Pattern.matches(regex, ipAddress);
    }

    public static boolean checkNickname(String nickname) {
        String regex = "^[a-zA-Z0-9\u4E00-\u9FA5_]+$";
        return Pattern.matches(regex, nickname);
    }
    

    public static boolean hasCrossSciptRiskInAddress(String str) {
        String regx = "[`~!@#$%^&*+=|{}':;',\\[\\].<>~!@#¥%……&*——+|{}【】‘;:”“’。,、?-]";
        if (str != null) {
            str = str.trim();
            Pattern p = Pattern.compile(regx, Pattern.CASE_INSENSITIVE);
            Matcher m = p.matcher(str);
            return m.find();
        }
        return false;
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343

推荐阅读更多精彩内容

  • 概述 正则表达式通常用于两种功能:验证和搜索/替换。用于验证时,通常需要在前后分别加上^和$,以匹配整个待验证字符...
    陈晨_Fly阅读 616评论 1 5
  • 初衷:看了很多视频、文章,最后却通通忘记了,别人的知识依旧是别人的,自己却什么都没获得。此系列文章旨在加深自己的印...
    DCbryant阅读 3,981评论 0 20
  • 推荐几个正则表达式编辑器 Debuggex :https://www.debuggex.com/ PyRegex:...
    木易林1阅读 11,458评论 9 151
  • 几个正则表达式编辑器 Debuggex :https://www.debuggex.com/ PyRegex:ht...
    没技术的BUG开发攻城狮阅读 4,581评论 0 23
  • 正则表达式到底是什么东西?字符是计算机软件处理文字时最基本的单位,可能是字母,数字,标点符号,空格,换行符,汉字等...
    狮子挽歌阅读 2,136评论 0 9