最近在做一個動態定義計算公式的問題,然后不可避免的用到了對象的動態添加屬性和字符串公式解析的問題,這里記錄一下公式解析的方法,比較初級.
關於正則表達式的語法規則使用以及例子說明,在文末.
先說需求解決.
一.利用 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
順便提供一個正則表達式的使用語法說明,校驗,測試的網站.