2.5正则表达式进阶
正则表达式的功能相当强大
Java 提供Pattern,Matcher类
Pattern:代表正则表达式本身
对正则进行预先编译处理
提高处理的效率
Matcher:代表正则匹配的结果
实现更加复杂的管理
如:进行子组的管理
四则运算-括号优先
Pattern
Matcher
串 解析
运算符操作数
运算符运算的先后次序关系
正常思路:双栈求解四则运算(逆波兰表达式)
这里不讨论逆波兰表达式,仅仅用正则来解决,虽然效率可能不是最高的
最内层括号先求值,获得最内层括号,正则匹配问题
String s = “2+3*(5*(12-6))”;
Pattern pt = Pattern.compile()
/* * 带有括号的计算 * 求四则运算表达式的值 Pattern Matcher 只有加减乘。除法具有特殊性 */ package RegularExpression; import java.util.regex.Matcher; import java.util.regex.Pattern; public class Equation { public static void main(String[] args) { String s = "2+3*(5*(12-6))"; Pattern pt = Pattern.compile("\\(([^\\(\\)]*)\\)"); Matcher m = pt.matcher(s); if(m.find()){ System.out.println(m.group(1));//直接提取子组 System.out.println(m.start()); System.out.println(m.end()); } } }
12-6 7 13
|
|
|
|
|
|
|
|
|
|
|
|
|
|
四则运算-没有括号乘法优先
package RegularExpression; import java.util.regex.Matcher; import java.util.regex.Pattern; public class Equation2 { public static void main(String[] args) { String s = "2+3*15*2-7"; Pattern pt = Pattern.compile("([0-9]+)(\\*)([0-9]+)"); Matcher m = pt.matcher(s); if(m.find()){ System.out.println(m.group()); System.out.println(m.group(1)); System.out.println(m.group(2)); System.out.println(m.group(3)); } } }
3*15 3 * 15
完整的示例代码如下:
package RegularExpression; /* 计算表达式的值(假设只有加法、减法、乘法) 23+15-16*(25+(6-3)+9*2) */ import java.util.regex.*; public class T1 { // 计算没有括号的表达式 static String calcuNoParen(String s) { if (s.length() < 1) return s; // 先把所有乘法消除 Pattern pat = Pattern.compile("([0-9]+)\\*([0-9]+)"); while (true) { Matcher mc = pat.matcher(s); if (mc.find() == false) break; // 已经没有乘法了 int res = Integer.parseInt(mc.group(1)) * Integer.parseInt(mc.group(2)); s = s.replace(mc.group(),res + ""); // 注意这里不能用replaceAll } // 再从左到右消除所有加法或减法 pat = Pattern.compile("([0-9]+)([\\+\\-])([0-9]+)"); while (true) { Matcher mc = pat.matcher(s); if (mc.find() == false) break; // 已经没有运算符了 int res = 0; if (mc.group(2).equals("+")) res = Integer.parseInt(mc.group(1)) + Integer.parseInt(mc.group(3)); else res = Integer.parseInt(mc.group(1)) - Integer.parseInt(mc.group(3)); s = s.replace(mc.group(),res + ""); // 注意这里不能用replaceAll } return s; } // 计算可能含有括号的表达式 static String calcu(String s) { s = s.replaceAll(" +",""); // 消除空格 Pattern pat = Pattern.compile("\\(([^\\(\\)]*)\\)"); while (true) { Matcher mc = pat.matcher(s); if (mc.find() == false) break; // 把括号内先计算,然后消除括号 s = s.replace(mc.group(),calcuNoParen(mc.group(1))); } return calcuNoParen(s); } public static void main(String[] args) { /* * String s = "23+15-16*(25+(6-3*2*1)+9*2)"; * * //任务:找到最内层括号中的内容,计算后替换掉 */ System.out.println(calcu("5 + 3 * 2 * (2+2-3) - 1")); } }
10
上述代码除了没有实现除法外,还不能有负号
|
|
|
展开串
实际开发中,常常会出现用到一批文件,而这些文件的文件名有某种规律,我们在表述的时候,往往习惯简写,但这样程序又不好识别。
比如:
c:/abc/xyz/k[11..19].dat
实际表示的就是:
c:/abc/xyz/k11.dat
c:/abc/xyz/k12.dat
c:/abc/xyz/k13.dat
c:/abc/xyz/k14.dat
c:/abc/xyz/k15.dat
c:/abc/xyz/k16.dat
c:/abc/xyz/k17.dat
c:/abc/xyz/k18.dat
c:/abc/xyz/k19.dat
本题目要求是:给定一个含有简写的串,要求展开为所有文件名。
简写的格式为:[整数..整数]
/* * 展开串 实际开发中,常常会出现用到一批文件,而这些文件的文件名有某种规律,我们在表述的时候,往往习惯简写,但这样程序又不好识别。 比如: c:/abc/xyz/k[11..19].dat 实际表示的就是: c:/abc/xyz/k11.dat c:/abc/xyz/k12.dat c:/abc/xyz/k13.dat c:/abc/xyz/k14.dat c:/abc/xyz/k15.dat c:/abc/xyz/k16.dat c:/abc/xyz/k17.dat c:/abc/xyz/k18.dat c:/abc/xyz/k19.dat 本题目要求是:给定一个含有简写的串,要求展开为所有文件名。 简写的格式为:[整数..整数] */ package RegularExpression; import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; public class UnfoldString { public static void main(String[] args) { String s = "c:/abc/xyz/k[11..19].dat"; for(int i=0;i<unfoldName(s).size();i++){ System.out.println(unfoldName(s).get(i)); } } public static List<String> unfoldName(String s){ ArrayList<String> list = new ArrayList<String>(); Pattern pt = Pattern.compile("\\[([0-9]+)\\.\\.([0-9]+)\\]");//匹配[11..19] Matcher m = pt.matcher(s); if(m.find()){ int start = Integer.valueOf(m.group(1)); int end = Integer.valueOf(m.group(2)); for(int i=start;i<=end;i++){ list.add(s.replace(m.group(),String.valueOf(i)));//用i替换[11..19] } } return list; } }
c:/abc/xyz/k11.dat c:/abc/xyz/k12.dat c:/abc/xyz/k13.dat c:/abc/xyz/k14.dat c:/abc/xyz/k15.dat c:/abc/xyz/k16.dat c:/abc/xyz/k17.dat c:/abc/xyz/k18.dat c:/abc/xyz/k19.dat