Java正则表达式

作为开发人员,正则是一定会接触到的内容,刚学习编程那时就开始用正则,提取爬虫爬取的页面内容。后面写Linux脚本,用正则过滤一些自己想要的内容。后续还是经常用到这块的知识点,还是需要整理下相关内容。

介绍

正则表达式(regex)即一种搜索字符串中模式(pattern)。模式可以是任意的字符串,或者是一个复杂的表达式。正则主要应用在字符串的搜索,编辑等操作上。

语法

1 如下egrep使用的是正则的语法,虽然是命令行,但内涵一样。.代表任意的字符串,所以egrep搜索字符的时候所以的字符都是红色的,是被匹配的,而搜索Hello的时候只有Hello被匹配。

每一种编程语言都有正则表达式的实现,但是不同的语言之间支持的内容有轻微的差别。

image-20191127072256674

常见正则规则

如下是一些常见的正则表达式类型。

正则表达式 Description
. 匹配任意字符
^regex 仅仅匹配regex必须在一行的开头字符。
regex$ 仅仅匹配regex出现在一行的末尾的字符串。比如 xxxxxregex。 而xxxregexyyy不行。
[abc] 集合匹配,匹配a,b,c
[abc][vz] 集合匹配,可以匹配 av,az,bv,bz,cv,cz
[^abc] 加上取反符号,即不匹配abc的内容
[a-d1-7] 匹配一个范围,具体位置可以是a-d中的任何一个字符,1-7之间的任何一个数字。
XlZ 匹配X或Y

正则元字符

一些预定义的元字符,让我们更容易使用正则表达式,可以看做替我们提前写好了上述的一些常见正则规则。

元字符 描述
\d 任何数字,即[0-9]
\D 任何非数字,即 [^0-9]
\s 任何空白字符,即 [ \t\n\x0b\r\f]
\S 任何非空白字符。即[^ \t\n\x0b\r\f]
\w 任意单词类型字符, 即 [a-zA-Z_0-9]
\W 任意非单词字符,即 [^\w]
\S+ 多个非空白字符
\b 匹配一个字边界,即字与空格间的位置。例如,"er\b"匹配"never"中的"er",但不匹配"verb"中的"er"。
\B 非字边界匹配。"er\B"匹配"verb"中的"er",但不匹配"never"中的"er"。

正则量词

量词即匹配一个字符串出现了多少次。

字符 描述
* 零次或多次匹配前面的字符或子表达式。例如,zo* 匹配"z"和"zoo"。* 等效于 {0,}。
+ 匹配一次或多次前面的字符,{1, }
? 匹配前一个字符不超过一次,即{0,1}
{X} X为数字,代表精确的匹配前一个字符几次。\d{3},代表精确匹配三个数字。
{X,Y} 匹配前一个字符,X次到Y次之间
*? 即只匹配一次就停止接下来的匹配。

Java使用

字符串中使用到正则的方法:

  • matches
  • split
  • replaceFirst
  • replaceAll

replace方法不支持正则表达式。

部分元字符测试

后续补充

提取数字

@Test
public void regextExtractNumber(){
    // 匹配任意的数字
    Pattern p = Pattern.compile("\\d+");
    Matcher m = p.matcher("string1234more567string890");
    while(m.find()) {
        System.out.println(m.group());
    }
}

匹配手机号

@Test
public void regexPhone(){
    // 手机号的第一位必须为 1。   ^[1]
    // 手机号的第二位必须为 3,4,5,7,8 中的任意一个。 [34578]
    // 紧接着有9位数字,只要是数字就行。[0-9]{9}
    // 没有其它额外的内容。最后一位$
    Pattern pattern = Pattern.compile("^[1][34578][0-9]{9}$");

    String p1 = "13855683754";
    String p2 = "15880975963";
    System.out.println(pattern.matcher(p1).matches());
    System.out.println(pattern.matcher(p2).matches());
}

匹配IP地址

这个属于比较复杂的案例,能看懂这个正则就ok了。

@Test
public void regexIpv4(){
    // IP地址长度不固定。因此可能出现误匹配
    // 将如下的正则表达式分为4段内容看即可。因为IP由三个  . 分隔开,以下正则也是又3个.分隔,最终以数字结尾。

    // ^[01]?\\d\\d?   如果是三个数字,第一位必须是0或1。但是可以为1位到2位数字。
    //  2[0-4]\\d    如果是以2开头的,那么接下来必须是0~4之间的一个数,第三位为任意数字
    //  25[0-5]    如果是以25开头的,那么最后一个数字只能是  0~5。
    // 其余一样
    String ip_pattern =
            "^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." +
                    "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." +
                    "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." +
                    "([01]?\\d\\d?|2[0-4]\\d|25[0-5])$";

    Pattern pattern = Pattern.compile(ip_pattern);

    List<String> strings = Arrays.asList(
            "0.1.1.1",
            "0.02.0.0",
            "192.168.1.1",
            "132.254.111.10",
            "127.0.0.1"
    );

    for (String string : strings) {
        System.out.println(pattern.matcher(string).matches());
    }
}

提取html中href地址。

@Test
    public void testHref(){
        String aTag = "<a href=\"https://sensiolabs.com\" title=\"SensioLabs, PHP services and software solutions for enterprise and community.\">\n" +
                "                                <img loading=\"eager\" height=\"17\" src=\"/images/pictos/slsponsor.svg\" alt=\"Symfony is sponsored by SensioLabs\">\n" +
                "                            </a>";

        // html的连接标签,属性为href。
        // 地址中不为空,但可能有?#等内容,因此用非空匹配。
        // href地址由""引起来,因此两边加上""
        // 使用正则的反向引用特性
        Pattern pattern = Pattern.compile("href=\"(\\S+)\".*");
        Matcher matcher = pattern.matcher(aTag);
        if (matcher.find()){
            System.out.println(matcher.group(1));
        }
    }

最后

今天先到这里了

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容

  • Java的正则表达式讲解:(为了能看清,本文正则表达式用中文的句号代替英文句点) 英文句点符号:匹配单个任意字符。...
    红姑娘阅读 4,218评论 0 2
  • 1. 正则表达式 1.1 什么是正则表达式 正则表达式: 定义一个搜索模式的字符串。 正则表达式可以用于搜索、编辑...
    数据萌新阅读 436评论 0 1
  • title: 用Java实现网络爬虫二之Java正则表达式tags: Java 网络爬虫 Spider Crawl...
    codingXiaxw阅读 866评论 0 3
  • 1. 正则表达式 1.1 什么是正则表达式 正则表达式: 定义一个搜索模式的字符串。 正则表达式可以用于搜索、编辑...
    __元昊__阅读 483评论 0 0
  • 东风有力千芽暖 午日无神万里闲 我送尾年寒尽去 依墙斜目伴春眠
    六点_0777阅读 538评论 0 17