您的位置:首页 > 其它

正则表达式:组与模式标记

2015-09-07 16:44 399 查看

前言

  终于又把看了不到一半的【java编程思想】重新拾起,但是遗憾的是前面的内容也是不记得什么了,所以为了以后能记得我看过的内容,还是随手写下这些知识点吧,方便以后查看。

正文

  今天要说明的是正则表达式中组和模式标记的内容。因为在课堂学习的内容中并没有这方面的知识,对我来说算是一个新知识点吧。

  组是用括号划分的正则表达式,可以根据组的编号来引用某个组。组号为0表示整个表达式,组号1表示被第一对括号括起的表达式,依次类推,如下:

A(B(C))D

  这个表达式中有三个组,组0是ABCD,组1是BC,组2是C

  我们来看下面的例子:–来自【java编程思想】

public class Example {
    public static void main(String[] args) {
        final String POEM = "Twas brillig, and the slithy toves\n"+
                "Did gyre and gimble in the wabe.\n"+
                "All mimsy were the borogoves,\n"+
                "And the mome raths outgrabe.\n\n"+
                "Beware the Jabberwock,my son,\n"+
                "The jaws that bite,the claws that catch.\n"+
                "Beware the Jubjub bird and shun\n"+
                "The frumious Bandersnatch.";
        Matcher m = Pattern.compile("(?m)(\\S+)\\s+((\\S+)\\s+(\\S+))$").matcher(POEM);
        while(m.find()){
            for(int j=0;j<=m.groupCount();j++){
                System.out.print("["+m.group(j)+"]");
            }
            System.out.println();
        }
    }
}


  下面是输出结果:

[the slithy toves][the][slithy toves][slithy][toves]
[in the wabe.][in][the wabe.][the][wabe.]
[were the borogoves,][were][the borogoves,][the][borogoves,]
[mome raths outgrabe.][mome][raths outgrabe.][raths][outgrabe.]
[the Jabberwock,my son,][the][Jabberwock,my son,][Jabberwock,my][son,]
[claws that catch.][claws][that catch.][that][catch.]
[bird and shun][bird][and shun][and][shun]
[The frumious Bandersnatch.][The][frumious Bandersnatch.][frumious][Bandersnatch.]


  就代码来说,我刚开始就有看不懂的地方了,(?m)是个什么东西,$又是什么东西?带着这样的问题就引出了模式标记的内容。

  Pattern类的一个compile方法有另一个版本,我们一直使用的compile(String regex),传入的是正则表达式字符串。而另一个版本是compile(String regex,int flag),第一个参数仍旧是正则表达式,而flag就是我们今天的重头戏,模式!

  flag的值是Pattern类中的以下常量:

Pattern.CANON_EQ:

指定此标志后,当且仅当其完整规范分解匹配时,两个字符才可视为匹配。例如,当指定此标志时,表达式 “a\u030A” 将与字符串 “\u00E5” 匹配。默认情况下,匹配不考虑采用规范等价。

Pattern.CASE_INSENSITIVE(?i):

默认情况下,不区分大小写的匹配假定仅匹配 US-ASCII 字符集中的字符。可以通过指定 UNICODE_CASE 标志连同此标志来启用 Unicode 感知的、不区分大小写的匹配。通过嵌入式标志表达式 (?i) 也可以启用不区分大小写的匹配。

Pattern.MULTILINE(?m):

在多行模式中,表达式 ^ 和 $ 仅分别在行结束符前后匹配,或者在输入序列的结尾处匹配。默认情况下,这些表达式仅在整个输入序列的开头和结尾处匹配。通过嵌入式标志表达式 (?m) 也可以启用多行模式。

  其余的常量我就不一一列举了,在上面的程序中我们用到了(?m),原来它是多行模式,$表示的是在结束符的末尾匹配,这样我大概就可以看懂程序了。

  (?m)(\S+)\s+((\S+)\s+(\S+))$这个正则表达式的匹配的就是从每行的最后三个单词,\S和\s表示意义我就不说了。

  从结果中我们也可以看到匹配的确实是每行的最后的三个单词。

  当然我们只是说明了模式匹配的内容,还有组的内容没有说,看输出的结果相比也能说明问题了吧。

  把上面的正则表达式的内容抽象成下面的式子:

(A)((B)(C))

  A表示每行最后三个单词的第一个为组1,BC为组2,B为组3,C为组4。这样就对输出结果没有任何疑问了。

  下面我再给出一个用^标记的例子。

String str = "java has regex\nJava has regex\n"+
    "J***A has pretty good regular expresstions\n"+
    "Regular expresstions are in Java";
    Pattern p = Pattern.compile("^java",Pattern.CASE_INSENSITIVE|Pattern.MULTILINE);
    Matcher m = p.matcher(str);
    while(m.find()){
        System.out.println(m.group());
    }


  下面是输出结果:

java
Java
J***A


  ”^“表示从一行的开始进行匹配,也就是说“^java”是所有以java开头都可以被匹配到。因为在这个例子中用到了Pattern.CASE_INSENSITIVE这个模式,忽略大小写,所以Java,J***A也都可以被匹配到。

小结

  正则表达式的内容果真是无穷丰富,以前只是能从一段字符串中匹配数字而已,虽然现在也没啥进步/(ㄒoㄒ)/~~

  关于正则表达式的应用方面,我用过一次,是小说阅读器的时候用来匹配章节名称进行智能断章,有兴趣的可以参考我的那一篇文章【android小说阅读器智能断章功能的实现
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: