CCF URL映射 java 100分详解 :巧妙地动态构造正则表达式

 主要想法:将<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);
	
	}

}

	

猜你喜欢

转载自blog.csdn.net/qq_36276117/article/details/84671777