编程算法基础-2.5正则表达式进阶

16 篇文章 0 订阅

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

 

static Pattern

compile(String regex)
          将给定的正则表达式编译到模式中。

 Matcher

matcher(CharSequence input)
          创建匹配给定输入与此模式的匹配器。

 boolean

find()
          尝试查找与该模式匹配的输入序列的下一个子序列。

 String

group()
          返回由以前匹配操作所匹配的输入子序列。

 String

group(int group)
          返回在以前匹配操作期间由给定组捕获的输入子序列。

 int

start()
          返回以前匹配的初始索引。

 int

end()
          返回最后匹配字符之后的偏移量。

 

四则运算-没有括号乘法优先

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

上述代码除了没有实现除法外,还不能有负号

 String

replace(char oldChar, char newChar)
          返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的。

 String

replace(CharSequence target, CharSequence replacement)
          使用指定的字面值替换序列替换此字符串所有匹配字面值目标序列的子字符串。

 

展开串

实际开发中,常常会出现用到一批文件,而这些文件的文件名有某种规律,我们在表述的时候,往往习惯简写,但这样程序又不好识别。

比如:

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



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值