ios 正則表達式

iOS在4.0裏也能夠用正則表達式了,功能也是至關強大。程序員

曾覺得本身已經掌握了正則表達式,這2天才明白正則表達式有多複雜,原來還有專門厚厚的一本書《正則表達式入門經典》。正則表達式

 

小程序的目標是匹配PGN棋譜中的着法部分。編程

規則就是:數字表示第幾次合,後面有個小句點,而後紅方着法,能夠跟評註,而後是黑方着法,能夠跟評註。評註是放在花括號中的,能夠單行,也能夠多行。小程序

1. 炮八平五 炮8平5編程語言

{ 紅方首着架中炮必走之着,聶棋聖還架中炮拼兌子力,戰術對頭。}工具

2. 炮五進五 象7進5測試

3. 炮二平五設計

{ 再架中炮也屬正着,如改走馬八進七,則象5退7,紅方帥府受攻,調試

固然若紅方仍再架中炮拼兌,那麼失去雙炮就難有做用了。code

}    馬8進7

... ...

人工很容易讀的棋譜,但用編程語言描述起來就不太容易了,最後寫出來的正則表達式是一段天書:

\d+\.\s+\w{4}\s*(\{(.|[\r\n])*?\})?\s*\w{4}\s*(\{(.|[\r\n])*?\})? 

放在iOS裏還要加上轉義符,就成了這樣:

\\d+\\.\\s+\\w{4}\\s*(\\{(.|[\\r\\n])*?\\})?\\s*\\w{4}\\s*(\\{(.|[\\r\\n])*?\\})?

因爲程序員還要提取出來回合數,紅方着法,紅方評註,黑方着法,黑方評註等重要信息,因此還要在上面的表達式里加上()這類的分組信息,最後的表達式更復雜了:

@"(\\d+)\\.\\s+(\\w{4})\\s*(\\{(?:.|[\\r\\n])*?\\})?\\s*(?:(\\w{4})\\s*(\\{(?:.|[\\r\\n])*?\\})?)?";

在編程序前,用了一款Windows上的小軟件RegexBuddy把正則表達式測試好許多遍才經過,若是直接上機調試會累個半死。

先把較爲簡單的正則表達式的意思折開來理解一下:

\d+\.            // 一個整數,後面跟着小圓點 
\s+                    // 1個以上的分隔符 
\w{4}               // 4個字符 
\s*                   // 0個以上的分隔符 
(\{(.|[\r\n])*?\})?   // 一行或多行的放在花括號中{}的註釋,紅方的招法評註 
\s*                   // 0個以上的分隔符 
(                      // 最後一回合時,能夠只有紅方的招法 
   \w{4}               // 4個字符 
   \s*                  // 0個以上的分隔符 
   (\{(.|[\r\n])*?\})?    // 一行或多行的放在花括號中{}的註釋,黑方的招法評註 
)?

這裏面涉及到的正則表達式語法:

\d 匹配任何一個數字,即[0-9]

\d+表示1個以上的數字

(\d+) 強行加上小括號,分組,至關把這個值緩衝起來,在代碼裏用[myString substringWithRange:[match rangeAtIndex:1]]能夠提取出來回合數

\. 表示小句點

\s 表示分隔符,包括空格、製表符和換行符

\s* 0個或多個分隔符

\w 表示字母、數字和下劃線,這裏還包括Unicode字符,不一樣的語言裏有些不一樣

\w{4} 表示4個非空白字符

. 表示任何一個字符,不包括換行符

.* 表示任何多個字符,固然也不包括換行符了

(.|[\r\n])* 表示任何多個字符,包括換行符,貪婪掃描

(.|[\r\n])*? 表示任何多個字符,包括換行符,懶惰掃描

(?:.|[\\r\\n])   以(?:開頭時的分組信息,表示不讀取到緩衝器裏,避免rangeAtIndex調用時產生反作用,後面還會遇到這樣的(?:寫法 

\{(.|[\r\n])*?\}  一條放在花括號中間的註釋語句,因爲包含了換行符,因此支持多行註釋

(\{(.|[\r\n])*?\})?  能夠沒有註釋,也能夠有1條註釋

 

在iOS裏用NSRegularExpression類來解析正則表達式,主要用法是:    

NSString *regTags = @"\\[(\\w*)\\s*\\\"(.*)\\\"]\\s*\\n";       // 設計好的正則表達式,最好先在小工具裏試驗好

NSRegularExpression *regex = [NSRegularExpressionregularExpressionWithPattern:regTags

                                              options:NSRegularExpressionCaseInsensitive    // 還能夠加一些選項,例如:不區分大小寫

                                              error:&error];

// 執行匹配的過程

NSArray *matches = [regex matchesInString:pgnText

                                options:0

                                range:NSMakeRange(0, [pgnText length])];

// 用下面的辦法來遍歷每一條匹配記錄

for (NSTextCheckingResult *match in matches) {

       NSRange matchRange = [match range];

       NSString *tagString = [pgnText substringWithRange:matchRange];  // 整個匹配串

       NSRange r1 = [match rangeAtIndex:1];

       if (!NSEqualRanges(r1, NSMakeRange(NSNotFound, 0))) {    // 由時分組1可能沒有找到相應的匹配,用這種辦法來判斷

           NSString *tagName = [pgnText substringWithRange:r1];  // 分組1所對應的串

       }

       NSString *tagValue = [pgnText substringWithRange:[match rangeAtIndex:2]];  // 分組2所對應的串

}

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息