【软件构造】实验三正则表达式的学习小总结
想总结的自己的问题:
正则表达式部分应该不会耗费特别多的时间,但对于实验三正则表达式这里我真的是出了很多时间,原因有下:
1.前后括号总有丢失或多余,一直匹配不上,反复实验耗费大量时间;
2.直接输入字符串和以文本方式读入有小区别,一开始测试的时候一直用直接输入字符串导致以文本输入时部分需要重新调整。
以下是对正则表达式的学习:
一、正则表达式定义及作用:正则表达式(regular expression)描述了一种字符串匹配的模式(pattern),可以用来检查一个串是否含有某种子串、将匹配的子串替换或者从某个串中取出符合某个条件的子串等。
二、正则表达式中常用:
字符 | 描述 |
---|---|
\w | 匹配字母、数字、下划线 |
\W | 匹配非字母、数字、下划线 |
\s | 匹配任意空白字符,相当于[\t\n\r\f] |
\S | 匹配任意非空字符 |
\d | 匹配任意数字,相当于[0-9] |
\D | 匹配非数字的字符 |
\A | 匹配字符串开头 |
\Z | 匹配字符串结尾,如果存在换行,只匹配到换行前的结束字符串 |
\z | 匹配字符串结尾,如果存在换行,同时还会匹配换行符 |
\G | 匹配最后匹配完成的位置 |
\n | 匹配一个换行符 |
\t | 匹配一个制表符 |
^ | 匹配一行字符串的开头 |
$ | 匹配一行字符串的结尾 |
. | 匹配任意字符,除了换行符 |
[^…] | 不在[]中的字符,比如[^abc]匹配除了a、b、c之外的字符 |
* | 匹配0个或多个表达式 |
+ | 匹配1个或多个表达式 |
? | 匹配0个或1个前面的正则表达式定义的片段,非贪婪方式 |
() | 匹配括号内的表达式,也表示一个组 |
{n} | 精确匹配n个前面的表达式,比如\d{n},代表n个数字 |
{n,m} | 匹配n到m次由前面正则表达式定义的片段,贪婪方式 |
三、正则表达式的实战设计:
比如实验三中对航班的正则表达式设计:
1.要求即示例:
2.分析设计:
第一行举例分析:
Flight为字符串,直接匹配,对时间和航班号根据规则应用上文规则设计即可。
Flight:(([0-9]{4})-((0[1-9])|(1[0-2]))-((3[0-1])|([1-2][0-9])|(0[1-9]))),([A-Z]{2}[0-9]{2}[0-9]?[0-9]?)
需要注意的:
对于换行:\n
对于“{”和“}”:在这里匹配需要写成:\\{ 和 \\}
剩下根据规则写即可。
完整正则表达式:
Pattern pattern = Pattern.compile("Flight:(([0-9]{4})-((0[1-9])|(1[0-2]))-((3[0-1])|([1-2][0-9])|(0[1-9]))),([A-Z]{2}[0-9]{2}[0-9]?[0-9]?)\n\\{\nDepartureAirport:([A-Z][a-z]*)\nArrivalAirport:([A-Z][a-z]*)\nDepatureTime:(([0-9]{4})-((0[1-9])|(1[0-2]))-((3[0-1])|([1-2][0-9])|(0[1-9])) ((2[0-4]|([0-1][0-9])):[0-5][0-9]))\nArrivalTime:(([0-9]{4})-((0[1-9])|(1[0-2]))-((3[0-1])|([1-2][0-9])|(0[1-9])) ((2[0-4]|([0-1][0-9])):[0-5][0-9]))\nPlane:((B|N)[0-9]{4})\n\\{\nType:([a-z]|([A-Z])([0-9]+))\nSeats:((600)|([1-5][0-9]{2})|([5-9][0-9]))\nAge:((([0-9])(\\.[0-9])?)|(([1-2][0-9])(\\.[0-9])?)|(30(\\.0)?))\n\\}\n\\}\n");
四、java中的正则表达式:
Pattern和Matcher:
1.定义:
Pattern 类:pattern 对象是一个正则表达式的编译表示
Matcher 类:Matcher 对象是对输入字符串进行解释和匹配操作的引擎
2.举例:
Pattern pattern = Pattern.compile("Flight:(([0-9]{4})-((0[1-9])|(1[0-2]))-((3[0-1])|([1-2][0-9])|(0[1-9]))),([A-Z]{2}[0-9]{2}[0-9]?[0-9]?)\n\\{\nDepartureAirport:([A-Z][a-z]*)\nArrivalAirport:([A-Z][a-z]*)\nDepatureTime:(([0-9]{4})-((0[1-9])|(1[0-2]))-((3[0-1])|([1-2][0-9])|(0[1-9])) ((2[0-4]|([0-1][0-9])):[0-5][0-9]))\nArrivalTime:(([0-9]{4})-((0[1-9])|(1[0-2]))-((3[0-1])|([1-2][0-9])|(0[1-9])) ((2[0-4]|([0-1][0-9])):[0-5][0-9]))\nPlane:((B|N)[0-9]{4})\n\\{\nType:([a-z]|([A-Z])([0-9]+))\nSeats:((600)|([1-5][0-9]{2})|([5-9][0-9]))\nAge:((([0-9])(\\.[0-9])?)|(([1-2][0-9])(\\.[0-9])?)|(30(\\.0)?))\n\\}\n\\}\n");
Matcher matcher = pattern.matcher(stringInfo.toString());//stringInfo为文本读入的部分
3.有关Matcher的方法:
a.find()方法:部分匹配,是查找输入串中与模式匹配的子串,如果该匹配的串有组还可以使用group()函数。find()能够接受一个整数作为参数,该整数表示字符串中字符的位置,并以其作为搜索的起点。
b.matches()方法:全部匹配,返回一个boolean类型,判断输入和设计的正则表达式是否匹配,匹配返回true,反之false。
c.有关组的方法:捕获组是把多个字符当一个单独单元进行处理的方法,它通过对括号内的字符分组来创建。可以通过调用 matcher 对象的 groupCount() 方法来查看表达式有多少个分组。groupCount() 方法返回一个 int 值,表示matcher对象当前有多个捕获组。group(int m)方法根据输入m,返回对应组的字符串。
4.需要注意的地方(在实验时也报过好多次错或费时间的点):
a.在使用group()方法获取组的之前,只有判断输入和正则表达式是否匹配之后才可以使用,否则会报错,如:
if(matcher.matches()){
String a = m.group(1);
...
}
b.不确定获取的字符串是否是想要的时可以新建的类小测试一下,输出所有的组。如:
BufferedReader bReader = new BufferedReader(new FileReader(new File("src/gui/1.txt")));
String line = "";
int count = 0;
StringBuilder stringInfo = new StringBuilder("");
while ((line = bReader.readLine()) != null) {
if (line.equals(""))
continue;
stringInfo.append(line + "\n");
count++;
if (count % 13 == 0) {
Pattern pattern = Pattern.compile("Flight:(([0-9]{4})-((0[1-9])|(1[0-2]))-((3[0-1])|([1-2][0-9])|(0[1-9]))),([A-Z]{2}[0-9]{2}[0-9]?[0-9]?)\n\\{\nDepartureAirport:([A-Z][a-z]*)\nArrivalAirport:([A-Z][a-z]*)\nDepatureTime:(([0-9]{4})-((0[1-9])|(1[0-2]))-((3[0-1])|([1-2][0-9])|(0[1-9])) ((2[0-4]|([0-1][0-9])):[0-5][0-9]))\nArrivalTime:(([0-9]{4})-((0[1-9])|(1[0-2]))-((3[0-1])|([1-2][0-9])|(0[1-9])) ((2[0-4]|([0-1][0-9])):[0-5][0-9]))\nPlane:((B|N)[0-9]{4})\n\\{\nType:([a-z]|([A-Z])([0-9]+))\nSeats:((600)|([1-5][0-9]{2})|([5-9][0-9]))\nAge:((([0-9])(\\.[0-9])?)|(([1-2][0-9])(\\.[0-9])?)|(30(\\.0)?))\n\\}\n\\}\n");
Matcher matcher = pattern.matcher(stringInfo.toString());
if(matcher.matches()) {
for(int i = 0; i<matcher.groupCount(); i++) {
System.out.println(i+"."+ matcher.group(i));
}
}
}
}
bReader.close();
测试文件内容如下:
输出如下:
这样就省去了判断想获得字符串是否是想要的字符串的时间和可能判断错误的麻烦。比如我想要飞机的出发机场,直接可以看出group(11)就是想要的。
/***********************************************************************************/
以上即为软件构造实验三正则表达式的学习小总结。