总是在项目中遇到比较小的问题,以前都没怎么放在心上,今天下班前在和同事讨论,怎么一段字符串中寻找相关的子字符串然后在将其替换掉,(如将链接替换成”link” “www.google.com” -> “link”)。我说我记得以前有处理过,看了自己的代码以后,笑了。。。
& Q& | S+ ]9 q9 f今天来说说链接的正则匹配 H3 N' t6 k6 t) ?! g
NSRegularExpression For Link (2016-04-18)
2 g# f* s# Z% c. g L. b4 s! M- #define TestRegularString @"\n This is the test string:1.www.google.com \n 2.http://www.google.com \n 3.https://www.google.com \n 4.Http://www.google.com.cn \n 5.ftp://www.google.com \n 6.http://127.0.0.1:16823 \n"" K9 |5 R2 e4 o$ i
复制代码就像将上面宏定义的字符串里面的链接找出来 并且匹配替换成”网页链接”) \9 l0 E3 v7 n
先上我以前处理时的代码:
& }. ?+ F0 h( c1 f - - (void)formatStringOne {9 w: a" T: G* q3 P- d) ~- g, A
- NSMutableString *formatedString = [TestRegularString mutableCopy];
! P0 ?0 H9 M: e' v/ \0 m5 } - static NSRegularExpression *iExpression = nil;
0 x8 f. u$ Q6 x$ c* O. Y6 X - NSError *error = nil;5 ~! k3 x5 `$ S5 \2 t* S" d
- iExpression = iExpression ?: [NSRegularExpression regularExpressionWithPattern:@"((http{0,1}|ftp)://[a-zA-Z0-9\\.\\-]+\\.([a-zA-Z]{2,4})(:\\d+)?(/[a-zA-Z0-9\\.\\-~!@#$%^&*+?:_/=<>]*)?)|(www.[a-zA-Z0-9\\.\\-]+\\.([a-zA-Z]{2,4})(:\\d+)?(/[a-zA-Z0-9\\.\\-~!@#$%^&*+?:_/=<>]*)?)" options:0 error:&error];
6 N, Q0 d2 {- q4 ]. I - if (error) {
7 @; r2 t$ |& [. ] - NSLog(@"error:%@",error);
8 A- i/ E" X* E2 ?% F6 H - return;
* L' b4 l: P$ I- \8 q - }" J5 E. H8 H+ G7 g/ a
- NSMutableArray *linkArray = [@[] mutableCopy];) ]( M7 T4 b$ B6 B" {2 b
- [linkArray addObjectsFromArray:[iExpression matchesInString:formatedString options:0 range:NSMakeRange(0,formatedString.length)]];
0 Z _; y2 h, @0 D - while (linkArray.count > 0) {
, G" Y) Z8 E* k9 B - NSTextCheckingResult *result = [linkArray firstObject];* C0 `8 Q3 Z/ \8 I
- [formatedString replaceCharactersInRange:result.range withString:@"网页链接"];0 z! Y0 ~. n; s$ o
-
! X. N |4 h& {1 G( y6 P/ G4 A - [linkArray removeAllObjects];
# ]% o; I/ t% g5 y6 O8 f, Z8 h - [linkArray addObjectsFromArray:[iExpression matchesInString:formatedString options:0 range:NSMakeRange(0,formatedString.length)]];
, z% B% m' `4 M' G, C# I6 d - }) M8 E0 ?' C: C L7 T
- NSLog(@"%s formatedString:%@",__func__,formatedString);
8 J6 P- ~+ |' y- T8 v" p - }
复制代码 6 c( {$ n5 A5 V! j$ q% w5 Y
哎哟,不知道从哪里找了段正则(正则我不是很熟悉。。。。) 功能能够实现,并且只遍历了n次,但是总感觉有点low。当时应该是知道得从第一个开始替换,后遇到了怎么获取替换后下一个位置的难题,然后就用了此方法。 再看从so上面找到的trick method
6 g& U$ d9 y4 i, Q) ?6 Q) Q - - (void)formatStringTwo {5 w! |6 Y: | f) t# [- m3 G
- // http://stackoverflow.com/questions/11379593/use-nsregularexpression-to-replace-each-match-with-a-result-of-method" ?2 d( T$ P$ ]. b
- NSError *error = nil;
5 T8 J: F2 G8 I' A/ ]; P: ~ - NSDataDetector *detector = [NSDataDetector dataDetectorWithTypes:NSTextCheckingTypeLink error:&error];3 A2 _+ i/ c+ _: ]" P6 u: }; J8 B
- if (error) {
+ o, P" c9 q# Y+ H' ] - NSLog(@"error:%@",error);- B/ l1 ^. r* C& [' u" ~ f* [
- return;
6 [7 g& V! Z3 p, i, F - }
& B9 [! x- M% h9 e - NSMutableString *formatedString = [TestRegularString mutableCopy];% U8 ?; }$ }+ }% v' ?6 s
- NSArray *linkArray = [detector matchesInString:formatedString options:0 range:NSMakeRange(0,formatedString.length)];
) d9 }" C$ _& t+ d - for (NSTextCheckingResult *result in [linkArray reverseObjectEnumerator]) {6 \7 A6 a/ l# B* ~9 O; g! {: x, c
- [formatedString replaceCharactersInRange:result.range withString:@"网页链接"];
& w0 c4 m7 U) @ - }
) T2 t$ Z2 L G - NSLog(@"%s formatedString:%@",__func__,formatedString);% K" C+ c7 Z: w5 |
- }
复制代码真的很nice,从后面开始替换,我就不用管替换前后的位置了。。。
1 P |1 @* m: L$ N; R! M3 e9 [再来一段利用偏移量处理的代码 Y n% S8 e! v& h! ~1 d7 K l
- - (void)formatStringThree {% Y; Q. y/ C8 p# z6 `% ?
- NSError *error = nil;1 `1 o. f: c6 |, J: j. |
- NSDataDetector *detector = [NSDataDetector dataDetectorWithTypes:NSTextCheckingTypeLink error:&error];( Y/ _7 I* A L, Y% [" P
- if (error) {
* d& z( ?! x4 o1 Q: q3 }: ]! } - NSLog(@"error:%@",error);
1 f! B' Q8 o) p Y1 x - return;
. V* u1 ~5 [: S( V+ K% m - }2 K$ y$ X) v- m! D2 x. g' O0 x
- NSMutableString *formatedString = [TestRegularString mutableCopy];' }* e N' |$ C+ f: ?
- NSInteger offset = 0;
* L6 S0 V! B0 |+ O0 ~! l - for (NSTextCheckingResult *result in [detector matchesInString:formatedString options:0 range:NSMakeRange(0,formatedString.length)]) {
4 L# P9 @" S1 B' d, _) u( H1 G - NSRange resultRange = result.range;/ r7 b& g t, n1 J# l
- resultRange.location += offset;
! m7 i: M2 l0 Q) g B$ [& \' ~ -
, f# n, f5 e0 x" Q4 n - // NSString *matchString = [detector replacementStringForResult:result inString:formatedString offset:offset template:@""];
9 g/ o6 L% C+ H5 e1 L - NSString *replaceString = @"网页链接";' ]$ Z: m6 D, V& s, R. B) L
- [formatedString replaceCharactersInRange:resultRange withString:replaceString];1 U/ \' E8 }! o$ B% h% k$ z3 g
- offset += ([replaceString length] - resultRange.length);+ G& C6 X2 z: A5 D u
- }
& }# a, f2 U3 N" A, v- O! p0 o -
: Z5 l% Q+ Y4 z- G2 T' _2 x4 } - NSLog(@"%s formatedString:%@",__func__,formatedString);
4 {' @3 U0 D; w' ^8 ~ - }
复制代码好吧 我们再来看看它们的输出结果5 F" D$ Z' X- C& M( c
- 2016-04-18 23:40:39.642 RegularExpressionTest[1642:305453] -[ViewController formatStringOne] formatedString:- D& Q, |/ r, b" ?
- This is the test string:1.网页链接 0 u) C$ ~# }: w6 w1 H/ }1 B' V' g" p
- 2.网页链接 0 f* q$ U5 c( m* O1 N+ K6 j
- 3.网页链接
# [; M+ c; R4 K0 g+ h4 f" F0 l* ` - 4.Http://网页链接
, F/ S8 \+ |! d6 \0 D# s; J - 5.网页链接 - S. Y3 S! g- ^0 Y B5 N, \) ^
- 6.http://127.0.0.1:16823 f+ v* _) n# @+ ~% Z9 H. ~8 h
- 2016-04-18 23:40:39.666 RegularExpressionTest[1642:305453] -[ViewController formatStringTwo] formatedString:7 L3 V' j/ N, _+ l" ^
- This is the test string:网页链接
3 [9 B: R+ V9 T( i# { - 2.网页链接
. S: s- O2 O2 k3 ~# B, j - 3.网页链接
5 u1 I6 p- F; E- H; b - 4.网页链接
' c) d/ U3 ]' W9 | - 5.网页链接
: C! B8 M, c$ V: U: {4 |7 _ - 6.网页链接
! f& |0 R# Y, G - 2016-04-18 23:40:39.668 RegularExpressionTest[1642:305453] -[ViewController formatStringThree] formatedString:$ ?# ^( k1 h7 D: d( N
- This is the test string:网页链接
+ R2 b* Y! Y; C! t' M - 2.网页链接 3 }; ?2 O: }3 J% B) _. Y/ F& p
- 3.网页链接 0 C; o1 R: ^3 E2 {8 b
- 4.网页链接 * k; Y& d2 _; Q( Y
- 5.网页链接 $ I( @7 V! F. E, H) f) s) m
- 6.网页链接
复制代码从上可以看出,我找的正则不是很牛逼,多看Apple Document总没错,Apple已经为了提供了一个检查数据的类 NSDataDetector,我们真没必要自己去写正则匹配,关键是还匹配错误;诶,一想到swift不是开源了,于是到NSRegularExpression.swift到全局搜索了下”link”关键字,想看看苹果的正则匹配是怎么写的,结果没有找到。。。。。。突然想到这么一句话:”知识就像内裤,看不见但是很重要”,对于我等程序猿来说,算法也是一样的。 " B( R! H6 |2 c
|