正则表达式的应用

在这里记录一下关于软件构造课程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 }
221 
222 MovieGraphFactory.java
View Code

 

posted @ 2018-06-09 13:29  匆匆那年匆匆走  阅读(226)  评论(0编辑  收藏  举报