前言
终于又把看了不到一半的【java编程思想】重新拾起,但是遗憾的是前面的内容也是不记得什么了,所以为了以后能记得我看过的内容,还是随手写下这些知识点吧,方便以后查看。
正文
今天要说明的是正则表达式中组和模式标记的内容。因为在课堂学习的内容中并没有这方面的知识,对我来说算是一个新知识点吧。
组是用括号划分的正则表达式,可以根据组的编号来引用某个组。组号为0表示整个表达式,组号1表示被第一对括号括起的表达式,依次类推,如下:
这个表达式中有三个组,组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,][the][Jabberwock,][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表示每行最后三个单词的第一个为组1,BC为组2,B为组3,C为组4。这样就对输出结果没有任何疑问了。
下面我再给出一个用^标记的例子。
String str = "java has regex\nJava has regex\n"+
"JAVA 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 JAVA
”^“表示从一行的开始进行匹配,也就是说“^java”是所有以java开头都可以被匹配到。因为在这个例子中用到了Pattern.CASE_INSENSITIVE这个模式,忽略大小写,所以Java,JAVA也都可以被匹配到。
小结
正则表达式的内容果真是无穷丰富,以前只是能从一段字符串中匹配数字而已,虽然现在也没啥进步/(ㄒoㄒ)/~~
关于正则表达式的应用方面,我用过一次,是小说阅读器的时候用来匹配章节名称进行智能断章,有兴趣的可以参考我的那一篇文章【android小说阅读器智能断章功能的实现】