正则表达式解析公式小结
最近在做一个动态定义计算公式的问题,然后不可避免的用到了对象的动态添加属性和字符串公式解析的问题,这里记录一下公式解析的方法,比较初级.
关于正则表达式的语法规则使用以及例子说明,在文末.
先说需求解决.
一.利用 string.split() 来直接分割字符串;
二.利用java中 Pattern 来定义相关规则后,匹配字符串中符合规则的字符串;
下面举个例子:
1 String formula = "xa+xb+xc*(xd-xe)-xf/xg"; 2 //第一种方式,直接分割 3 String spiltRules = "\\+|-|\\*|/|=|\\(|\\)"; 4 String[] array = formula.split(spiltRules); 5 for (String s : array) { 6 System.out.println(s); 7 } 8 9 System.out.println("=====分割线====="); 10 //第二种方式,利用正则匹配 11 List listCompile = new ArrayList(); 12 Matcher matcher = Pattern.compile("\\bx\\w{1}").matcher(formula);// 用正则匹配 13 while (matcher.find()) { 14 listCompile.add(matcher.group(0)); 15 System.out.println(matcher.group(0)); 16 } 17 System.out.println(listCompile);
控制台输出结果为:
1.关于直接使用string中的split()直接分割(上面第3,4行代码),这里控制台会出现空行,原因是在formula.split()之后,如果有两个连续的,规则中能匹配到的运算符,就会在array中出现空的一个元素,所以如果世界使用此种方法分割字符串公式,要做处理,再将分割出来的元素(后面的变量)存入变量集合.
2.如果使用java中Pattern.compile(),先定义匹配规则,这里"\\bx\\w{1}"意思为,以x开头,然后任意一位数字或者字母,知道结束.匹配成功后存入新的list,由于利用正则表达式匹配相关需要的字段,就不会存在上面那种如果多个运算符连在一起,会出现空元素的情况,这个集合可以不用再经过处理就可以直接使用.
然后下面还详细说一下正则表达式的使用:
先说正则表达式的样子,其实我们经常使用这东西,只不过联想不到而已,就比如说我们经常使用的Ctrl+f或者ctrl+h等等,如果我们需要查找一个单词"hi",那我们就会输入"hi"来查找,这算是最简单的正则表达式了,他由两个字符组成,前一个字符是h,后一个是i,通常,处理正则表达式的工具会提供一个忽略大小写的选项,如果选中了这个选项,它可以匹配hi,HI,Hi,hI这四种情况中的任意一种。
不幸的是,很多单词里包含hi这两个连续的字符,比如him,history,high等等。用hi来查找的话,这里边的hi也会被找出来。如果要精确地查找hi这个单词的话,我们应该使用\bhi\b。
好了,这里出现了新的东西,就是 \b . \b是正则表达式规定的一个特殊代码(就是我所谓的正则表达式的语法)(某些人叫它元字符,metacharacter)
字符 | 描述 |
---|---|
\ | 将下一个字符标记为一个特殊字符、或一个原义字符、或一个后向引用、或一个八进制转义符。 |
^ | 匹配输入字符串的开始位置。如果设置了 RegExp 对象的Multiline 属性,^ 也匹配 ’\n’ 或 ’\r’ 之后的位置。 |
$ | 匹配输入字符串的结束位置。如果设置了 RegExp 对象的Multiline 属性,$ 也匹配 ’\n’ 或 ’\r’ 之前的位置。 |
* | 匹配前面的子表达式零次或多次。 |
+ | 匹配前面的子表达式一次或多次。+ 等价于 {1,}。 |
? | 匹配前面的子表达式零次或一次。? 等价于 {0,1}。 |
{n} n | 是一个非负整数,匹配确定的n 次。 |
{n,} n | 是一个非负整数,至少匹配n 次。 |
{n,m} | m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。在逗号和两个数之间不能有空格。 |
? | 当该字符紧跟在任何一个其他限制符 (*, +, ?, {n}, {n,}, {n,m}) 后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。 |
. | 匹配除 "\n" 之外的任何单个字符。要匹配包括 ’\n’ 在内的任何字符,请使用象 ’[.\n]’ 的模式。 |
(pattern) | 匹配pattern 并获取这一匹配。 (?:pattern) 匹配pattern 但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。 (?=pattern) 正向预查,在任何匹配 pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。 (?!pattern) 负向预查,与(?=pattern)作用相反 x|y 匹配 x 或 y。 |
[xyz] | 字符集合。 |
[^xyz] | 负值字符集合。 |
[a-z] | 字符范围,匹配指定范围内的任意字符。 |
[^a-z] | 负值字符范围,匹配任何不在指定范围内的任意字符。 |
\b | 匹配一个单词边界,也就是指单词和空格间的位置。 |
\B | 匹配非单词边界。 |
\cx | 匹配由x指明的控制字符。 |
\d | 匹配一个数字字符。等价于 [0-9]。 |
\D | 匹配一个非数字字符。等价于 [^0-9]。 |
? \f | 匹配一个换页符。等价于 \x0c 和 \cL。 |
\n | 匹配一个换行符。等价于 \x0a 和 \cJ。 |
\r | 匹配一个回车符。等价于 \x0d 和 \cM。 |
\s | 匹配任何空白字符,包括空格、制表符、换页符等等。等价于[ \f\n\r\t\v]。 |
\S | 匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。 |
\t | 匹配一个制表符。等价于 \x09 和 \cI。 |
\v | 匹配一个垂直制表符。等价于 \x0b 和 \cK。 |
\w | 匹配包括下划线的任何单词字符。等价于’[A-Za-z0-9_]’。 |
\W | 匹配任何非单词字符。等价于 ’[^A-Za-z0-9_]’。 |
\xn | 匹配 n,其中 n 为十六进制转义值。十六进制转义值必须为确定的两个数字长。 |
\num | 匹配 num,其中num是一个正整数。对所获取的匹配的引用。 |
\n | 标识一个八进制转义值或一个后向引用。如果 \n 之前至少 n 个获取的子表达式,则 n 为后向引用。否则,如果 n 为八进制数字 (0-7),则 n 为一个八进制转义值。 |
\nm | 标识一个八进制转义值或一个后向引用。如果 \nm 之前至少有is preceded by at least nm 个获取得子表达式,则 nm 为后向引用。如果 \nm 之前至少有 n 个获取,则 n 为一个后跟文字 m 的后向引用。如果前面的条件都不满足,若 n 和 m 均为八进制数字 (0-7),则 \nm 将匹配八进制转义值 nm。 \nml 如果 n 为八进制数字 (0-3),且 m 和 l 均为八进制数字 (0-7),则匹配八. |
这里面的就所谓的元字符,举个例子
\d 表示匹配一个数字字符。等价于 [0-9]。后面的{3}就是连续匹配三位.
所以\d{3}-\d{8} 和 \d\d\d-\d\d\d\d\d\d\d\d 的意思一样,代表"3个数字-8个数字"的格式的字符串.
所以再上面的例子中,
这三个红线框中的都会被找出来.
注:
关于"\b"和"\\b"的区别:
\b : 就是正则表达式中单纯的语法;
\\b :这是java中转义(转译)字符,"\\"代表反斜杠. 在字符串中定义的话,在正则匹配规则中,等同于"\b".
Matcher matcher = ttern.compile("\\bx\\w{1}").matcher(formula);// 用正则匹配 就比如说这句,"\\bx\\w{1}"在最后使用的时候,就是"\bx\w{1}"
补充一点转译字符:
特殊字符:
\":双引号
\':单引号
\\:反斜线
控制字符:
\' 单引号字符
\\ 反斜杠字符
\r 回车
\n 换行
关于转译字符,详细一点的可以去这看看,或者去百度上搜索一下. http://blog.csdn.net/generalyy0/article/details/7307267
顺便提供一个正则表达式的使用语法说明,校验,测试的网站.