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