在这里记录一下关于软件构造课程Lab3中关于正则表达式的应用。

  在实验内容中,要求用正则表达式来匹配读入文件的内容,从而取得构建图需要的相关信息。

  举个例子,读入的文件(GraphPoetTestFile.txt)内容如下:

  先说一下文件内容中的数据格式:

  ①一定有一行,第一个单词为"GraphType",后面是一个空格、一个'='、一个空格,加上一个"类型名"

  ②一定有一行,第一个单词为"GraphName",后面是一个空格、一个'='、一个空格,加上一个"图的名字"

  ③一定有一行,第一个单词为"VertexType"/"EdgeType",后面是一个空格、一个'='、一个空格,加上若干个"顶点类型",不同顶点类型之间用','和空格隔开

  ④一定有若干行,第一个单词为"Vertex",后面是一个空格,一个'='、一个空格、一个左尖括号'<',加上若干个"数据信息",最后用右尖括号'>'结束(中间可能仍有尖括号来界定属性信息)

  ⑤一定有若干行,第一个单词为"Edge",后面是一个空格,一个'='、一个空格、一个左尖括号'<',加上若干个"数据信息",信息项之间用','和空格隔开,最后用右尖括号'>'结束

  ⑥可能存在若干行,第一个单词为"HyperEdge",后面是一个空格,一个'='、一个空格、一个左尖括号'<',加上若干个"数据信息",信息项之间用','和空格隔开,包含一组大括号'{''}'来界定的属性信息,最后用右尖括号'>'结束

  下面说一下对于这个问题而言,我的解决思路:

  首先,分析读入文件的格式,每一行读入引号中的数据项个数可能不一致,有的行只包含一项,有的行却包含多项,因此没有一种完美的正则表达式能直接全部读取所有引号的数据项。同时,考虑到还有尖括号'<>'以及大括号'{}'来界定的情况,这种直接构建完整正则表达式进行匹配的方式似乎不存在或者说使用情况比较复杂。

  先说明两种基本的匹配字符串的方式,一种是最大化地进行匹配字符串,一种是最小化地进行匹配字符串。

  比如,对于一个字符串/Introduction = "I", "Am", "Steven", "Shen"/(这里用'/'来表示字符串界定符以避免产生歧义),最大化地进行匹配的话,我要得到的就是引号区间界定的整个字符串匹配,即/"I", "Am", "Steven", "Shen"/;最小化地进行匹配的话,我要得到的就是引号区间界定的一小部分字符串匹配,即/I/,再次重复进行匹配就会依次得到/Am/、/Steven/、/Shen/。这两种正则表达式在Java中的具体字符串表示格式就是max = "(\".+\")",min = "\"([^\"]+)\""。

  下面回到问题上来,我的解决思路有两种:

  第一种方式,通过max和min的使用,细致化地获取数据

  对每一行先进行这样的匹配String pattern1 = "(\\w+) = (\".+\")"; 即每行先是一个单词,一个空格,一个'=',一个空格,后加一个max型的匹配,得到'='后所有信息项。匹配上面的那个文件,第一行匹配结果就是/GraphType/、/"MovieGraph"/,第三行匹配结果就是/VertexType/、/"Movie", "Actor", "Director"/。此时,我们判断第一个读入的单词的内容,即可确定该如何处理'='后面的信息项。此时再对第二个获取的串(通过max匹配得到的串)进行最小化地匹配,第一行就得到了/MovieGraph/,第三行就得到了/Movie/、/Actor/、/Director/三个项。类似地,把界定范围改成尖括号内的内容,同样也可以获取Vertex以及Edge的信息。

  这种解决方式总的思路就是通过匹配每行第一个单词来确定如何处理这行数据'='后的数据项。然后通过最大化地匹配'='后的数据,进一步对其用最小化匹配进行划分,得到具体的数据项。

  第二种方式,通过max的使用,结合对字符串的操作达成目标

  类似于上面说的,得到每行第一个单词后,用最大化匹配来得到'='后的数据项,此时匹配的内容就是/"I", "Am", "Steven", "Shen"/,然后对这个字符串使用String的split方法(当然,split的参数列表实际上接收的就是一个正则表达式的字符串)。这里的split方法就是这样split(",\\s")。这样,/"I", "Am", "Steven", "Shen"/就变成了/"I"/、/"Am"/、/"Steven"/、/"Shen"/,他们存储在一个String数组中,这时还要数组中每个串求子串,从而去掉每个串两端的引号(")。即通过String的subString方法,得到/I/、/Am/、/Steven/、/Shen/。

  这种解决方式总的思路就是先获取要读取的数据块,在对数据块用String的操作来完成每个需要读取的数据项。这种方式相比于前面那种比较麻烦,原因在于求子串、分割过程比较繁琐,不如上面那种方法的用最小化匹配方便快捷。

  这两种方法的正则表达式匹配串并获取,都用到了group方法,这些内容在Java的String和正则表达式部分都有详细介绍,这里就不再赘述了。

  至于文件中可能存在的匹配不同界定符的情况,可以类似地考虑如何实现。主要思路就在上面,具体实现时可以通过每行数据项的个数等确定性信息来进行信息读取,使得处理更灵活。

  下面附上针对这种MovieGraph的处理代码。  

  1. package factory;
  2.  
  3. import java.util.*;
  4. import java.util.regex.*;
  5. import java.io.*;
  6. import vertex.*;
  7. import edge.*;
  8. import graph.*;
  9.  
  10. public class MovieGraphFactory {
  11. public static MovieGraph createGraph(String filePath) {
  12. String GraphType = "";
  13. String GraphName = "";
  14. String VertexType = "";
  15. List<String> VertexTypes = new ArrayList<>();
  16. String EdgeType = "";
  17. List<String> EdgeTypes = new ArrayList<>();
  18. Set<String> fullVertexInfo = new HashSet<>();
  19. Set<String> fullEdgeInfo = new HashSet<>();
  20. Set<String> fullHyperEdgeInfo = new HashSet<>();
  21. List<Vertex> vertexList = new ArrayList<>();
  22. List<Edge> edgeList = new ArrayList<>();
  23. List<Edge> hyperList = new ArrayList<>();
  24. String pattern1 = "(\\w+) = (\".+\")";
  25. String pattern2 = "(\\w+) = <(.+)>";
  26. String pattern3 = ",? ?\"([^\"]+)\"";
  27. Pattern p = Pattern.compile(pattern1);
  28. Matcher parse1 = p.matcher("");
  29. p = Pattern.compile(pattern2);
  30. Matcher parse2 = p.matcher("");
  31. MovieGraph graph = null;
  32. try {
  33. File file = new File(filePath);
  34. InputStreamReader readin = new InputStreamReader(new FileInputStream(file));
  35. BufferedReader bufReadin = new BufferedReader(readin);
  36. String line;
  37. int i = 1;
  38. while((line = bufReadin.readLine()) != null) {
  39. parse1.reset(line);
  40. parse2.reset(line);
  41. if(parse1.find()) {
  42. if(parse1.groupCount() == 2) {
  43. if(parse1.group(1).equals("GraphType")) {
  44. GraphType = parse1.group(2);
  45. if(!GraphType.equals("\"MovieGraph\"")) {
  46. System.out.println("Error! the graph must be MovieGraph rather be " + GraphType);
  47. bufReadin.close();
  48. throw new RuntimeException();
  49. }
  50. }
  51. if(parse1.group(1).equals("GraphName"))
  52. GraphName = parse1.group(2);
  53. if(parse1.group(1).equals("VertexType"))
  54. VertexType = parse1.group(2);
  55. if(parse1.group(1).equals("EdgeType"))
  56. EdgeType = parse1.group(2);
  57. }
  58. } else if(parse2.find()) {
  59. if(parse2.groupCount() == 2) {
  60. if(parse2.group(1).equals("Vertex"))
  61. fullVertexInfo.add(parse2.group(2));
  62. if(parse2.group(1).equals("Edge"))
  63. fullEdgeInfo.add(parse2.group(2));
  64. if(parse2.group(1).equals("HyperEdge"))
  65. fullHyperEdgeInfo.add(parse2.group(2));
  66. }
  67. }
  68. }
  69. p = Pattern.compile(pattern3);
  70. Matcher parse3 = p.matcher(GraphType);
  71. if(parse3.find())
  72. GraphType = parse3.group(1);
  73. parse3 = p.matcher(GraphName);
  74. if(parse3.find())
  75. GraphName = parse3.group(1);
  76. parse3 = p.matcher(VertexType);
  77. while(parse3.find()) {
  78. VertexTypes.add(parse3.group(1));
  79. }
  80. parse3 = p.matcher(EdgeType);
  81. while(parse3.find()) {
  82. EdgeTypes.add(parse3.group(1));
  83. }
  84.  
  85. String label = "", type = "";
  86. String[] fields = null;
  87.  
  88. for(String temp : fullVertexInfo) {
  89. i = 0;
  90. Vertex point = null;
  91. parse3 = p.matcher(temp);
  92. if(parse3.find())
  93. label = parse3.group(1);
  94. if(parse3.find()) {
  95. type = parse3.group(1);
  96. }
  97. switch(type) {
  98. case "Actor" :
  99. fields = new String[2];
  100. break;
  101. case "Director" :
  102. fields = new String[2];
  103. break;
  104. case "Movie" :
  105. fields = new String[3];
  106. break;
  107. default :
  108. System.out.println("Error. The graph can't contain other vertex " + type);
  109. bufReadin.close();
  110. throw new RuntimeException();
  111. }
  112. while(parse3.find()) {
  113. fields[i++] = parse3.group(1);
  114. }
  115. switch(type) {
  116. case "Actor" :
  117. point = ActorVertexFactory.createVertex(label, fields);
  118. break;
  119. case "Director" :
  120. point = DirectorVertexFactory.createVertex(label, fields);
  121. break;
  122. case "Movie" :
  123. point = MovieVertexFactory.createVertex(label, fields);
  124. break;
  125. default :
  126. break;
  127. }
  128. vertexList.add(point);
  129. }
  130.  
  131. for(String temp : fullEdgeInfo) {
  132. parse3 = p.matcher(temp);
  133. Double weight = 0.0;
  134. Vertex point1 = null, point2 = null;
  135. Edge edge = null;
  136. if(parse3.find())
  137. label = parse3.group(1);
  138. if(parse3.find())
  139. type = parse3.group(1);
  140. if(parse3.find())
  141. weight = Double.parseDouble(parse3.group(1));
  142. if(parse3.find())
  143. for(Vertex start : vertexList) {
  144. if(parse3.group(1).equals(start.getLabel())) {
  145. point1 = start;
  146. break;
  147. }
  148. }
  149. if(parse3.find())
  150. for(Vertex end : vertexList) {
  151. if(parse3.group(1).equals(end.getLabel())) {
  152. point2 = end;
  153. break;
  154. }
  155. }
  156. if(parse3.find())
  157. if(!parse3.group(1).equals("No")) {
  158. bufReadin.close();
  159. throw new RuntimeException();
  160. }
  161. List<Vertex> arg = new ArrayList<>();
  162. arg.add(point1); arg.add(point2);
  163. switch(type) {
  164. case "MovieActorRelation" :
  165. edge = MovieActorRelationFactory.createEdge(label, arg, weight);
  166. break;
  167. case "MovieDirectorRelation" :
  168. edge = MovieDirectorRelationFactory.createEdge(label, arg, -1.0);
  169. break;
  170. default :
  171. System.out.println("Error, the graph can't contain other edge " + type);
  172. bufReadin.close();
  173. throw new RuntimeException();
  174. }
  175. edgeList.add(edge);
  176. }
  177.  
  178. for(String temp : fullHyperEdgeInfo) {
  179. parse3 = p.matcher(temp);
  180. Edge hyper = null;
  181. if(parse3.find()) {
  182. label = parse3.group(1);
  183. }
  184. if(parse3.find())
  185. type = parse3.group(1);
  186. List<Vertex> hyperVertices = new ArrayList<>();
  187. while(parse3.find()) {
  188. for(Vertex temppoint : vertexList) {
  189. if(parse3.group(1).equals(temppoint.getLabel())) {
  190. hyperVertices.add(temppoint);
  191. break;
  192. }
  193. }
  194. }
  195. hyper = SameMovieHyperEdgeFactory.createEdge(label, hyperVertices, -1.0);
  196. hyperList.add(hyper);
  197. }
  198.  
  199. graph = new MovieGraph(GraphName);
  200. for(Vertex temp : vertexList) {
  201. graph.addVertex(temp);
  202. }
  203. for(Edge temp : edgeList) {
  204. graph.addEdge(temp);
  205. }
  206. for(Edge temp : hyperList) {
  207. graph.addEdge(temp);
  208. }
  209.  
  210. System.out.println("***** vertexList's length : " + vertexList.size());
  211. System.out.println("***** edgeList's length : " + edgeList.size());
  212. System.out.println("***** hyperList's length : " + hyperList.size());
  213. System.out.println("Vertex:" + fullVertexInfo.size()+ "\n" + fullVertexInfo + "\n" + "Edge:" + fullEdgeInfo.size() + "\n" + fullEdgeInfo + "\n" + "HyperEdge:" + fullHyperEdgeInfo.size() + "\n" + fullHyperEdgeInfo);
  214. bufReadin.close();
  215. } catch(Exception e) {
  216. e.printStackTrace();
  217. }
  218. return graph;
  219. }
  220. }

MovieGraphFactory.java

  思路比较简单,事实证明可行。代码写得不高端...

  见证菜鸡成长...

  

关于Lab3中对于正则表达式的应用的更多相关文章

  1. PHP中有关正则表达式的函数集锦

    之前学正则表达式的目的是想从网上抓取点小说啊,文档啊,还有获取相应的视频连接然后批量下载.当时初学PHP根本不知道PHP有专门抓包的工具,就像Simple_html_dom.php(在我的其他博文中有 ...

  2. JavaScript中的正则表达式(终结篇)

    JavaScript中的正则表达式(终结篇) 在之前的几篇文章中,我们了解了正则表达式的基本语法,但那些语法不是针对于某一个特定语言的.这篇博文我们将通过下面几个部分来了解正则表达式在JavaScri ...

  3. Coursera-Getting and Cleaning Data-week4-R语言中的正则表达式以及文本处理

    博客总目录:http://www.cnblogs.com/weibaar/p/4507801.html Thursday, January 29, 2015 补上第四周笔记,以及本次课程总结. 第四周 ...

  4. 9.JAVA中的正则表达式

    一.JAVA中的正则表达式 1.概念:以某种特定的方式描述字符串 1.Java中正则表达式的规则 ?          #{0,1}-?有一个-或者没有 \\           #表示一个" ...

  5. Python::re 模块 -- 在Python中使用正则表达式

    前言 这篇文章,并不是对正则表达式的介绍,而是对Python中如何结合re模块使用正则表达式的介绍.文章的侧重点是如何使用re模块在Python语言中使用正则表达式,对于Python表达式的语法和详细 ...

  6. 工作随笔——UIButton的EdgeInsets + Swift中的正则表达式;

    1.UIButton的EdgeInsets UIButton的EdgeInsets方法,是用来设置title和image对于上左下右四个方向的偏移,但是很奇怪的是,刚开始只有Image,titile也 ...

  7. Javascript中的正则表达式

    Javascript中的正则表达式 刚开始接触正则表达式的时候,觉得这是个很死板的东西(没办法,计算机不能像人眼一样能很快的辨认出我们需要的结果,它需要一定的规则来对它进行限制),了解的越多,发现这个 ...

  8. 在Visual Studio中使用正则表达式匹配换行和批量替换

    系统环境:Windows 8.1 Enterprise Update 2 x64 开发环境:Mircosoft Visual Studio Ultimate 2013 Update 2 RC 问题:如 ...

  9. 浅谈JavaScript中的正则表达式

    引言 对于正则表达式我想作为程序员肯定使用过它,那天书般的表达方式,我用一次就记住它了.这篇博客先介绍一些正则表达式的内容,然后介绍JavaScript中对正则表达式特有的改进.下面开始介绍正则表达式 ...

随机推荐

  1. 安卓开发:Password verification failed

    2019年8月5日更新: 我把Android Studio升级到3.4.2版本后,发现下图中的按钮已经不见了,所以本文中之前的创建签名文件的方法已经不行了- ...3.4.2版本是这样的---> ...

  2. ubuntu 命令记录

    1.su root  进入root模式 2.ifconfig 查看ip地址 3.ls 查看文件 4./etc/init.d/matrix-gui-2.0 stop 关闭matrix界面 5.cd /文 ...

  3. Webflux是什么东东

    转自:百家号-薇薇心语 各位Javaer们,大家都在用SpringMVC吧?当我们不亦乐乎的用着SpringMVC框架的时候,Spring5.x又悄(da)无(zhang)声(qi)息(gu)的推出了 ...

  4. Bugku-CTF加密篇之简单加密(e6Z9i~]8R~U~QHE{RnY{QXg~QnQ{^XVlRXlp^XI5Q6Q6SKY8jUAA)

    简单加密   e6Z9i~]8R~U~QHE{RnY{QXg~QnQ{^XVlRXlp^XI5Q6Q6SKY8jUAA    

  5. 《Web安全攻防 渗透测试实战指南 》 学习笔记 (三)

    Web安全攻防 渗透测试实战指南   学习笔记 (三) burp suite详解                                                 是一款集成化渗透测试工 ...

  6. Install fail! Error: EBUSY: resource busy or locked, symlink

    前些日子从github上下载了一个项目 然后放在桌面上  ,但是运行的时候 报了Install fail! Error: EBUSY: resource busy or locked, symlink ...

  7. 【剑指Offer面试编程题】题目1509:树中两个结点的最低公共祖先--九度OJ

    题目描述: 给定一棵树,同时给出树中的两个结点,求它们的最低公共祖先. 输入: 输入可能包含多个测试样例. 对于每个测试案例,输入的第一行为一个数n(0<n<1000),代表测试样例的个数 ...

  8. 洛谷 T2691 桶哥的问题——送桶

    嗯... 题目链接:https://www.luogu.org/problem/T2691 这道题有一点贪心的思想吧...并且思路与题目是倒着来的(貌似这种思路已经很常见的... 先举个栗子: 引出思 ...

  9. [原]NTP时钟同步服务设置

    服务器列表 192.168.0.2 ntp服务端 192.168.0.3 ntp客户端 192.168.0.4 ntp客户端 192.168.0.5 ntp客户端 注:以下操作均以root操作 一.N ...

  10. request库解析中文

    官网地址: http://cn.python-requests.org/zh_CN/latest/ 高级用法 本篇文档涵盖了 Requests 的一些高级特性. 会话对象 会话对象让你能够跨请求保持某 ...