CCF URL對映 java 100分詳解 :巧妙地動態構造正則表示式
阿新 • • 發佈:2018-12-01
主要想法:將<int>替換成([0-9]+),將<str>替換成([^/]+),將<path>替換成(.+),
例如,/articles/<int>/<int>/<str>/ 替換之後就會變成/articles/([0-9]+)/([^/]+)/(.+)/ ,這樣它就成了一個正則表示式,可以完全匹配到/articles/1985/09/aloha/,並且利用小括號的分組功能可以將其中的引數提取出來
但這樣有一個麻煩,這個討厭的麻煩就是整數引數要去除前導0,要注意,如果對應的是<str>或<path>則不能去除,
所以麻煩就在於要判斷它對應的是不是<int>,因此這一步我用了大量程式碼繁瑣的步驟來判斷。
import java.util.ArrayList; import java.util.Scanner; import java.util.regex.Matcher; import java.util.regex.Pattern; public class Main { public static void main(String[] args) { // TODO Auto-generated method stub Scanner scan=new Scanner(System.in); int m=scan.nextInt(); int n=scan.nextInt(); scan.nextLine(); String[] input=new String[m];//儲存原有的規則內容以便前導0判斷<int> String[][] rules=new String[m][2];這個陣列第一個元素存的是構造後的正則,第二個是規則名 for(int i=0;i<m;i++) { input[i]=scan.nextLine(); rules[i] =input[i].split(" ");//按空格將規則分兩半 rules[i][0]=rules[i][0].replaceAll("<int>", "([0-9]+)").replaceAll("<str>","([^/]+)").replaceAll("<path>","(.+)"); }//將規則變成正則表示式 String[] output=new String[n]; for(int i=0;i<n;i++) { String url=scan.nextLine(); if(!url.matches("[/A-Za-z0-9\\-\\._]+")) {//判斷輸入是否合法 output[i]="404"; continue; } boolean flag=false;//標記是否已經匹配到了 for(int j=0;j<m;j++) {//遍歷每一項規則 String[] rule = rules[j]; Pattern p=Pattern.compile(rule[0]); Matcher matcher=p.matcher(url); if(matcher.matches()) {//如果完全匹配,注意區別:find()是部分匹配 flag=true; output[i]=rule[1];//先存入規則名 for(int k=1;k<=matcher.groupCount();k++) {//逐一獲取引數值 String param=matcher.group(k);//對每個引數值,判斷它是否以0開頭,如果不是,就直接接到輸出後面,如果是,則要判斷它對應的引數型別是否為<int> if(!param.startsWith("0"))//如果是<str>或<path>怎麼辦 output[i]=output[i]+" "+param; else {//找出該條規則中的所有引數佔位符,就是形如<xxx>的 Pattern pp=Pattern.compile("(<[a-z]+>)"); Matcher mat=pp.matcher(input[j]); int count=0; while(mat.find()) { count++;//找到第K個佔位符,因為這個引數值是第k個,所以對應的是該條規則中的第k個引數,也就是第k個<xxx> if(count==k) break; } if(mat.group(1).equals("<int>")) param=param.substring(1); output[i]=output[i]+" "+param; }//else startsWith("0") }//for groupCount break; //既然找到了第一個完全匹配的規則,搞完了就跳出 }//if matches }//for j:m if(flag==false) output[i]="404";//遍歷了所有規則也沒找到匹配的 }//for i:n for(String s:output) System.out.println(s); } }