iOS開發(fā) -正則表達(dá)式的使用和匹配內(nèi)容

我們經(jīng)常會(huì)遇到驗(yàn)證一個(gè)用戶的操作數(shù)據(jù)是否合法,我們最好的方式是用正則去檢測用戶的行為操作是否正確

來個(gè)圖片放松一下啊
來個(gè)圖片放松一下啊

正則匹配整數(shù)和浮點(diǎn)數(shù)

需求:檢測文本中的數(shù)字,并改變顏色凭戴,數(shù)字都是序列化的樣式文本:當(dāng)前已經(jīng)使用的存儲(chǔ)
空間大小為3.2GB,下載文件占用788MB粥庄,還剩余6.7GB空間薯酝,總?cè)萘繛?2GB.
我們需要匹配出來一下幾個(gè)數(shù)字
3.2GB 
788MB
6.7GB
12GB

我們?nèi)绻谝谎劭瓷先ツ阌X得要如何去做呢,我們今天要的不僅是匹配母截,還要獲取到對(duì)應(yīng)的數(shù)值
這個(gè)匹配我們使用系統(tǒng)的NSRegularExpression ,進(jìn)行內(nèi)容的匹配到忽,開始我想到了三種規(guī)則:如下

  1. \\d*\\.\\d*[M|G]B 這種規(guī)則只適合含有小數(shù)點(diǎn)的數(shù)值,等到項(xiàng)目中用的時(shí)候才發(fā)現(xiàn)整數(shù)沒有匹配上去清寇,繼續(xù)修改下面
  2. (((\\d*\\.\\d*)MB)|((\\d*\\.\\d*)GB)) 這個(gè)是一位PHP大牛寫的喘漏,我仔細(xì)分解了一下,似乎我寫的那個(gè)就可以了华烟,但是還是匹配到整數(shù)就錯(cuò)誤翩迈。
  3. (\\d*(\\.\\d*)?)[M|G]B 這個(gè)才是我們想要的,既能匹配小數(shù)盔夜,又可以匹配整數(shù)负饲,這個(gè)是我考慮之后稍作修改堤魁,檢測結(jié)果是正常的

第三種情況的匹配代碼實(shí)例如下:

    NSString *searchText = @"當(dāng)前手機(jī)已使用存儲(chǔ)大小為3.2GB,已下載文件占用899MB返十,剩余空間大小5.8GB妥泉,當(dāng)前總?cè)萘繛?2GB";
    NSError *error = NULL;
    //@"\\d*\\.\\d*[M|G]B"   匹配字符串中連續(xù)規(guī)則的數(shù)字序列
    //@"(((\\d*\\.\\d*)MB)|((\\d*\\.\\d*)GB))"  匹配規(guī)則全部序列
    NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"(\\d*(\\.\\d*)?)[M|G]B" 
    options:NSRegularExpressionCaseInsensitive error:&error];
    NSTextCheckingResult *result = [regex firstMatchInString:searchText options:0 range:NSMakeRange(0, [searchText length])];
    NSArray * matches1 = [regex matchesInString:searchText options:NSMatchingReportProgress range:NSMakeRange(0, [searchText length])];
    for (NSTextCheckingResult * test in matches1) {
       
        NSString *tagValuestr = [searchText substringWithRange:test.range];
         NSLog(@"tagvalue = %@",tagValuestr);
    }
    if (result) {
        NSLog(@"%@", [searchText substringWithRange:result.range]);
    }

控制臺(tái)輸出結(jié)果為:

2016-03-15 17:41:19.608 RegularExp[54814:2551313] tagvalue = 3.2GB
2016-03-15 17:41:19.608 RegularExp[54814:2551313] tagvalue = 899MB
2016-03-15 17:41:19.608 RegularExp[54814:2551313] tagvalue = 5.8GB
2016-03-15 17:41:19.608 RegularExp[54814:2551313] tagvalue = 12GB
2016-03-15 17:41:19.609 RegularExp[54814:2551313] 3.2GB

我們可以發(fā)現(xiàn),這個(gè)就是我們想要的結(jié)果
result 是單個(gè)結(jié)果洞坑,使用matches是獲取多個(gè)結(jié)果

我們再說一下獲取URL參數(shù)的正則

代碼如下:

 NSError *error1;
    NSString *regTags=[[NSString alloc] initWithFormat:@"(^|&|\\?)+%@=+([^&]*)(&|$)",@"adc"];
    NSRegularExpression *regex1 = [NSRegularExpression regularExpressionWithPattern:regTags
                                                                           options:NSRegularExpressionCaseInsensitive
                                                                             error:&error1];
    
    // 執(zhí)行匹配的過程
     NSString *webaddress=@"http://www.baidu.com/dd/adb.htm?adc=e12&xx=lkw&dalsjd=12";
    NSArray *matches = [regex1 matchesInString:webaddress
                                      options:0
                                        range:NSMakeRange(0, [webaddress length])];
    for (NSTextCheckingResult *match in matches) {
        //NSRange matchRange = [match range];
        //NSString *tagString = [webaddress substringWithRange:matchRange];  // 整個(gè)匹配串
        //        NSRange r1 = [match rangeAtIndex:1];
        //        if (!NSEqualRanges(r1, NSMakeRange(NSNotFound, 0))) {    // 由時(shí)分組1可能沒有找到相應(yīng)的匹配盲链,用這種辦法來判斷
        //            //NSString *tagName = [webaddress substringWithRange:r1];  // 分組1所對(duì)應(yīng)的串
        //            return @"";
        //        }
        
        NSString *tagValue = [webaddress substringWithRange:[match rangeAtIndex:2]];  // 分組2所對(duì)應(yīng)的串
        //    NSLog(@"分組2所對(duì)應(yīng)的串:%@\n",tagValue);
        NSLog(@"tagvalue = %@",tagValue);
        
    }

控制臺(tái)的輸出

2016-03-15 17:41:19.609 RegularExp[54814:2551313] tagvalue = e12

以上是對(duì)NSRegularExpression 這個(gè)類的使用

下面我們擴(kuò)展一些實(shí)用的東西:

方法一、 使用謂詞NSPredicate創(chuàng)建正則表達(dá)式

一般我們只使用謂詞僅供開發(fā)者判斷用戶輸入的字符串是否合法迟杂,并沒有其他要求

// 編寫正則表達(dá)式:只能是數(shù)字或英文刽沾,或兩者都存在
NSString *regex = @"^[a-z0-9A-Z]*$";
// 創(chuàng)建謂詞對(duì)象并設(shè)定條件的表達(dá)式
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];
// 判斷的字符串
NSString *str = @"Hello100";
// 對(duì)字符串進(jìn)行判斷
if ([predicate evaluateWithObject:str]) {
    NSLog(@"Match");
}

上面判斷之后的結(jié)果就是會(huì)輸出 Match ,如果我們替換一下字符串為-逢慌、= 悠轩! 之類的,那么判斷就不會(huì)進(jìn)入攻泼。

方法二火架、 通過NSRegularExpression 獲取指定的對(duì)象

我們可以過濾掉一些東西獲取到我們想要的結(jié)果,代碼更清晰:

NSString *url = @"8888@163.com";
NSError *error;
// 創(chuàng)建NSRegularExpression對(duì)象并指定正則表達(dá)式
NSRegularExpression *regex = [NSRegularExpression
                regularExpressionWithPattern:@"[^@]*\\."
                options:0
                error:&error];
if (!error) { // 如果沒有錯(cuò)誤
  // 獲取特特定字符串的范圍
  NSTextCheckingResult *match = [regex firstMatchInString:url
                          options:0
                            range:NSMakeRange(0, [url length])];
  if (match) {
    // 截獲特定的字符串
    NSString *result = [url substringWithRange:match.range];
    NSLog(@"%@",result);
  }
} else { // 如果有錯(cuò)誤忙菠,則把錯(cuò)誤打印出來
  NSLog(@"error - %@", error);
}

上面這個(gè)列子我們是從特定字符串中檢索以“@”開頭 “.” 結(jié)尾的區(qū)間字符串何鸡,所以最終獲取到的字符串結(jié)尾包括點(diǎn)“.”,最終輸出的是“163.”;

方法三牛欢、NSRegularExpression 獲取多個(gè)結(jié)果骡男,也就是最上面我們的需求

我們講解一個(gè)獲取連續(xù)數(shù)字序列的正則

NSString *regex = @"\\-\\d*\\.";
NSString *str = @"-111.-666.-888.";
NSError *error;
NSRegularExpression *regular = [NSRegularExpression regularExpressionWithPattern:regex
                                                                         options:NSRegularExpressionCaseInsensitive
                                                                           error:&error];
// 對(duì)str字符串進(jìn)行匹配
NSArray *matches = [regular matchesInString:str
                                    options:0
                                      range:NSMakeRange(0, str.length)];
// 遍歷匹配后的每一條記錄
for (NSTextCheckingResult *match in matches) {
    NSRange range = [match range];
    NSString *mStr = [str substringWithRange:range];
    NSLog(@"%@", mStr);
}

@"\\-\\d*\\.";我們這里的規(guī)則是-號(hào)開頭,\ 代表特殊字符轉(zhuǎn)義傍睹,不參與匹配隔盛,“\d” 相當(dāng)于 [0-9] ,有\(zhòng) 開始的規(guī)則,需要加入轉(zhuǎn)義字符“拾稳、”
方法三的輸出結(jié)果是

-111.
-666.
-888.

通過打印結(jié)果吮炕,我們可以得知,我們通過方法三的結(jié)果是多個(gè)访得,獲取到我們想要的結(jié)果龙亲。

注:我們把常用的字符注釋一下

  1. “\” :將下一個(gè)字符標(biāo)記為一個(gè)特殊字符、或一個(gè)原義字符悍抑、或者一個(gè)向后引用鳄炉,或者一個(gè)八進(jìn)制轉(zhuǎn)義符。例如:“\\n”匹配“\n” "\n"搜骡。序列“\\” 匹配“\” 而 “\(” 匹配“(”拂盯。
  2. "^": 匹配輸入字符串的開始位置,如果設(shè)置了RegExp對(duì)象的Multiline屬性记靡,^也匹配“\n”或“\r”之后的位置磕仅。
  3. "$" : 匹配輸入字符串的結(jié)束位置珊豹。如果設(shè)置了RegExp對(duì)象的Multiline屬性,$也匹配“\n”或“\r”之前的位置榕订。
  4. "*": 匹配前面的子表達(dá)式零次或多次(大于等于0次)店茶。例如,zo*能匹配“z”劫恒,“zo”以及“zoo”贩幻。*等價(jià)于{0,}。
  5. "+":匹配前面的子表達(dá)式一次或多次(大于等于1次)两嘴。例如丛楚,“zo+”能匹配“zo”以及“zoo”,但不能匹配“z”憔辫。+等價(jià)于{1,}趣些。
  6. "?": 匹配前面的子表達(dá)式零次或一次。例如贰您,“do(es)?”可以匹配“do”或“does”中的“do”坏平。?等價(jià)于{0,1}。
  7. "{n}":n是一個(gè)非負(fù)整數(shù)锦亦。匹配確定的n次舶替。例如,“o{2}”不能匹配“Bob”中的“o”杠园,但是能匹配“food”中的兩個(gè)o顾瞪。
  8. "{n,}":n是一個(gè)非負(fù)整數(shù)。至少匹配n次抛蚁。例如陈醒,“o{2,}”不能匹配“Bob”中的“o”,但能匹配“foooood”中的所有o瞧甩《危“o{1,}”等價(jià)于“o+”∏着洌“o{0,}”則等價(jià)于“o*”尘应。
  9. "{n,m}":m和n均為非負(fù)整數(shù)惶凝,其中n<=m吼虎。最少匹配n次且最多匹配m次。例如苍鲜,“o{1,3}”將匹配“fooooood”中的前三個(gè)o思灰。“o{0,1}”等價(jià)于“o?”混滔。請(qǐng)注意在逗號(hào)和兩個(gè)數(shù)之間不能有空格洒疚。
  10. "?":當(dāng)該字符緊跟在任何一個(gè)其他限制符(*,+,?歹颓,{n},{n,}油湖,{n,m})后面時(shí)巍扛,匹配模式是非貪婪的。非貪婪模式盡可能少的匹配所搜索的字符串乏德,而默認(rèn)的貪婪模式則盡可能多的匹配所搜索的字符串撤奸。例如,對(duì)于字符串“oooo”喊括,“o+?”將匹配單個(gè)“o”胧瓜,而“o+”將匹配所有“o”。
  11. ".":匹配除“\r\n”之外的任何單個(gè)字符郑什。要匹配包括“\r\n”在內(nèi)的任何字符府喳,請(qǐng)使用像“[\s\S]”的模式。
  12. "\s" :"匹配任何空白字符蘑拯,包括空格钝满、制表符、換頁符等等强胰。等價(jià)于[ \f\n\r\t\v]舱沧。"

正則先說到這里,請(qǐng)查看鏈接:正則使用說明

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末偶洋,一起剝皮案震驚了整個(gè)濱河市熟吏,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌玄窝,老刑警劉巖牵寺,帶你破解...
    沈念sama閱讀 217,509評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異恩脂,居然都是意外死亡帽氓,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門俩块,熙熙樓的掌柜王于貴愁眉苦臉地迎上來黎休,“玉大人,你說我怎么就攤上這事玉凯∈迫” “怎么了?”我有些...
    開封第一講書人閱讀 163,875評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵漫仆,是天一觀的道長捎拯。 經(jīng)常有香客問我,道長盲厌,這世上最難降的妖魔是什么署照? 我笑而不...
    開封第一講書人閱讀 58,441評(píng)論 1 293
  • 正文 為了忘掉前任祸泪,我火速辦了婚禮,結(jié)果婚禮上建芙,老公的妹妹穿的比我還像新娘没隘。我一直安慰自己,他們只是感情好禁荸,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評(píng)論 6 392
  • 文/花漫 我一把揭開白布升略。 她就那樣靜靜地躺著,像睡著了一般屡限。 火紅的嫁衣襯著肌膚如雪品嚣。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,365評(píng)論 1 302
  • 那天钧大,我揣著相機(jī)與錄音翰撑,去河邊找鬼。 笑死啊央,一個(gè)胖子當(dāng)著我的面吹牛眶诈,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播瓜饥,決...
    沈念sama閱讀 40,190評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼逝撬,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了乓土?” 一聲冷哼從身側(cè)響起宪潮,我...
    開封第一講書人閱讀 39,062評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎趣苏,沒想到半個(gè)月后狡相,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,500評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡食磕,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評(píng)論 3 335
  • 正文 我和宋清朗相戀三年尽棕,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片彬伦。...
    茶點(diǎn)故事閱讀 39,834評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡滔悉,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出单绑,到底是詐尸還是另有隱情回官,我是刑警寧澤,帶...
    沈念sama閱讀 35,559評(píng)論 5 345
  • 正文 年R本政府宣布询张,位于F島的核電站孙乖,受9級(jí)特大地震影響浙炼,放射性物質(zhì)發(fā)生泄漏份氧。R本人自食惡果不足惜唯袄,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蜗帜。 院中可真熱鬧恋拷,春花似錦、人聲如沸厅缺。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽湘捎。三九已至诀豁,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間窥妇,已是汗流浹背舷胜。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評(píng)論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留活翩,地道東北人烹骨。 一個(gè)月前我還...
    沈念sama閱讀 47,958評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像材泄,于是被迫代替她去往敵國和親沮焕。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容