NSHipster: NSRegularExpression 中文解析指南

更新:11-15 名人轶事 我要投稿 纠错 投诉

大家好,如果您还对NSHipster: NSRegularExpression 中文解析指南不太了解,没有关系,今天就由本站为大家分享NSHipster: NSRegularExpression 中文解析指南的知识,包括的问题都会给大家分析到,还望可以解决大家的问题,下面我们就开始吧!

遇到问题了,哦,得用NSRegularExpression了。

事实上,有些事情你应该注意。

正则表达式是一种DSL,有一些讨论。说他也不好,毕竟Regex里充满了各种符号。说得好,Regex 简单、强大且用途广泛。

众所周知,Cocoa 为NSRegularExpression 设计了一个冗长的API。首先将其与Ruby 进行比较。这段Ruby代码的功能是从HTML代码片段中提取URL。

htmlSource="有问题吗?更正?@NSHipsteroron GitHub。"

linkRegex=/]*href="([^"]*)"[^]*/i

链接=htmlSource.scan(linkRegex)

放置(链接)

#https://twitter.com/NSHipste

#https://github.com/NSHipster/articles

用三行Ruby 代码实现。

现在看看在Swift 中使用NSRegularExpression 来实现相同的功能(从HTML 代码片段中提取URL。)

让htmlSource="有问题吗?更正吗?@NSHipsteror

在GitHub 上。

let linkRegexPattern="]*href="([^"]*)"[^]*" //相比Ruby 多了一个转义符""

让linkRegex=尝试! NSRegularExpression(pattern: linkRegexPattern, options:caseInsensitive )

让匹配=linkRegex.matches(in: htmlSource, range: NSRange(location: 0, length: htmlSource.utf16.count))

让links=matches.map{ 结果-String in

让hrefRange=result.rangeAt(1)

让start=String.UTF16Index(encodedOffset: hrefRange.location)

let end=String.UTF16Index(encodedOffset: hrefRange.location + hrefRange.length)

返回字符串(htmlSource.utf16[开始.

}

打印(链接)

//["https://twitter.com/NSHipster", "https://github.com/NSHipster/articles"]

{

渲染:

简单说明:

第一段,

第二段[^]* 要求任何后续字符串不得包含。

第三段,href="。查找紧随其后的href="

第四段,([^"]*),任何后续字符串不得包含"

第五段"[^]*首先进行转义,然后要求后面的字符串满足*和之间的,排除。

}

NSRegularExpression 很糟糕,仅此而已。

原文(英文原文)并没有简单地解释正则表达式(你必须学习通配符‘*’‘+’、反向引用‘^’、前进‘[]’等)

学习Swift 中的正则表达式、NSRegularExpression、NSTextCheckingResult,注意其中的难点和特殊情况,就可以轻松上手了。

字符串方法 ,NSStringMethods

开始使用Cocoa 中的正则表达式,当然不使用NSRegularExpression。

NSString中的range(of:)方法可以实现轻量级的字符串搜索。您需要使用.regularExpression 来切换正则表达式模式。 (OC的NSString对应Swift的String)

OC代码

NSString * source=@"对于NSSet 和NSDictionary,打破.";

//作用是匹配字符串中看起来像Cocoa type类型的单词

//例如:UIButton、NSCharacterSet、NSURLSession

NSString * typePattern=@"[A-Z]{3,}[A-Za-z0-9]+";

NSRange typeRange=[源rangeOfString: typePattern options: NSRegularExpressionSearch];

if( typeRange.location!=NSNotFound ){

NSLog(@"第一个类型: %@",[sourcesubstringWithRange:typeRange]);

//首先输入: NSSet

}

SWIFT代码

let source="对于NSSet 和NSDictionary,突破性的."

//匹配任何看起来像Cocoa type: 的东西

//UIButton、NSCharacterSet、NSURLSession 等

让typePattern="[A-Z]{3,}[A-Za-z0-9]+"

if let typeRange=source.range(of: typePattern , options:regularExpression){

print("第一个类型: (source[typeRange])")

//首先输入: NSSet

}

{

链接:https://regex101.com/r/U7TC8v/1

第一个段[A-Z]{3,} 用于匹配A-Z 中的至少3 个字符。

第二段,[A-Za-z0-9]+,用于匹配集合中至少一个字符,A-Z之间加a-z,0-9之间加

}

替换也是常用的功能。对于相同的选项,请使用replacementOccurrences(of:with:)。

接下来,使用看起来很奇怪的代码在上一句中的coco 类型单词周围添加括号。看起来更清楚了。

OC代码

NSString * MarkUpSource=[源stringByReplacingOccurrencesOfString:typePattern withString: @""$0`" options: NSRegularExpressionSearch 范围: NSMakeRange(0,source.length)];

NSLog(@"%@",markedUpSource);

//"对于`NSSet` 和`NSDictionary`,破坏性的."

SWIFT代码

让markedUpSource=source.replacingOccurrences(of: typePattern, with: "`$0`", options:regularExpression)

打印(标记源)

//"对于`NSSet` 和`NSDictionary`,破坏性的.""

{

阐明:

这里有一个在正则表达式中获取正则分段的概念。

请参阅此链接:https://stackoverflow.com/questions/432493/how-do-you-access-the-matched-groups-in-a-javascript-regular-expression

}

使用上面的替换模板,正则表达式可以处理派生分组。在西方,有关于元音的字母转换,

OC代码

NSString * ourcesay=[source stringByReplacingOccurrencesOfString: @"([bcdfghjklmnpqrstvwxyz]*)([a-z]+)" withString: @"$2$1ay" options: NSRegularExpressionSearch | NSCaseInsensitiveSearch range: NSMakeRange(0,source.length)];

NSLog(@"%@",sourcesay);

//"orFay etNSSay anday ictionaryNSDay, ethay eakingbray."

SWIFT代码

让ourcesay=source.replacingOccurrences(of: "([bcdfghjklmnpqrstvwxyz]*)([a-z]+)", with: "$2$1ay", options: [.regularExpression,caseInsensitive])

打印(来源说)

//"orFay etNSSay anday ictionaryNSDay, ethay eakingbray."

{

链接: https://regex101.com/r/lZxWuY/2

第一段([bcdfghjklmnpqrstvwxyz]*) 匹配不包含e i o u 的任何长度的任何英文字母。

第二段([a-z]+) 匹配至少一种长度的任意英文字母

}

在很多需要正则化的场景下,上述两种方法就足够了。要实现复杂的功能,需要使用NSRegularExpression 类。首先,解决Swift 新手常犯的一个常见错误。

NSRangeand Swift

与Foundation 的NSString 相比,Swift 具有更大的范围和更复杂的API 来处理字符串的字符和子字符串。 Swift 的标准库有四个接口来处理字符数据。您可以使用字符、Unicode 标量、UTF-8 代码和UTF-16 代码来获取字符串数据。

这与NSRegularExpression有关。许多NSRegularExpression 方法使用NSRange 并使用NSTextCheckingResult 对象来保存匹配的数据。 NSRange使用整数类型来记录其起始点位置和字符长度length。但字符串String不使用整数作为索引。

让范围=NSRange(位置: 4,长度: 5)

//以下代码不可编辑

来源[范围]

来源.字符[范围]

source.substring(with:range)

source.substring(with:range.toRange()!)

快点。

Swift中的String实际上是通过utf16接口进行操作的,这和Foundation框架下的NSString API是一样的。您可以通过utf16接口的方法使用整数类型创建索引。

让start=String.UTF16Index(encodedOffset: range.location)

let end=String.UTF16Index(encodedOffset: range.location + range.length)

让substring=String(source.utf16[开始.

//子字符串现在是"NSSet"

下面是一些String Util 代码,用于调用Swift 相关的常规语法糖,给人一种Objective-C 的感觉。

扩展字符串{

///这个nsrange属性包含字符串的所有范围

var nsrange: NSRange{

返回NSRange(位置:0,长度:utf16.count)

}

///使用前面给出的nsrange 属性返回一个字符串。

///如果字符串中没有这样的范围,则为nil

func 子字符串(带有nsrange: NSRange)-字符串?{

Guard let range=Range(nsrange, in: self)

否则{返回零}

返回字符串(自身[范围])

}

///返回与之前取出的nsrange属性相同的范围。

///如果字符串中没有这样的范围,则为nil

函数范围(来自nsrange: NSRange)-范围?{

Guard let range=Range(nsrange, in: self)

否则{返回零}

返回范围

}

}

接下来我们要体验的NSRegularExpression就使用了上面的Util方法。

NSRegularExpression和 NSTextCheckingResult

之前,我们学习了如何查找字符串中第一个匹配的数据并将其替换为匹配的数据。对于更复杂的情况,必须使用NSRegularExpression。首先创建一个简单的文本匹配miniPattern 以在文本中查找*bold* 和_italic_

要创建NSRegularExpression 对象,需要传入与规则匹配的字符串模式,并且有一些选项可以设置。 miniPattern 查找以星号* 或下划线_ 开头的匹配单词。找到星号或下划线后,匹配一个到多个字符的格式,并使用找到的第一个匹配字符再次匹配以终止搜索。匹配的首字母和文本将保存在查询结果中。

OC代码

NSString * miniPattern=@"([*_])(.+?)\1";

NSError * 错误=nil;

NSRegularExpression * miniFormatter=[ NSRegularExpression RegularExpressionWithPattern: miniPattern options: NSRegularExpressionDotMatchesLineSeparators error: 错误];

SWIFT代码

让miniPattern="([*_])(.+?)\1"

让miniFormatter=尝试! NSRegularExpression(pattern: miniPattern, options:dotMatchesLineSeparators)

//如果miniPattern 错误,NSRegularExpression 初始化会抛出异常。

如果模式不正确,NSRegularExpression 初始化将抛出异常。一旦创建了NSRegularExpression 对象,它就可以用来处理不同的字符串。

{

阐明:

"([*_])(.+?)\1" ,这个正则表达式分为三部分,

第一段([*_])匹配方括号中的任意字符,即or;

第二段(.+?)匹配任意长度大于1的字符串;

第三段,\1,有一个转义字符,并且匹配之前获得的第一个等效字符串。

}

OC代码

NSString * text=@"MiniFormatter 处理*粗体*和_斜体_文本。";

NSArray* matches=[miniFormatter matchesInString: text options: kNilOptions range: NSMakeRange(0,text.length)];

//matches.count==2

SWIFT代码

let text="MiniFormatter 处理*粗体*和_斜体_文本。"

让matches=miniFormatter.matches(in: text, options: [], range: text.nsrange )

//matches.count==2

调用matches(in:options:range:) 方法来检索包含NSTextCheckingResult 元素的数组。 NSTextCheckingResult 类型由各种文本处理类使用,例如NSDataDetector 和NSSpellChecker。在返回的数组中,匹配项有一个NSTextCheckingResult。

通常你想要得到的是匹配的范围,它在每个结果的range属性中。通常需要获取的是正则表达式中任意匹配的范围。您可以通过numberOfRanges 属性和rangeAt(_:) 方法查找指定范围。

范围(at:)

返回范围表示的结果类型。

range(at:)方法,返回的结果是对应的范围

讨论

结果必须至少有一个范围,但可以选择有更多范围(例如,表示正则表达式捕获组)。

传递range(at:) 值0 始终返回therange 属性的值。其他范围(如果有)将具有从1 到numberOfRanges-1 的索引。

讨论,

返回的结果必须至少有一个范围。通常还有更多,可选。 (正则表达式捕获组,对应)

range(at:) 方法返回的第一个结果是range 属性的值。如果还有的话,返回结果对应的索引是从1到numberOfRanges-1

引用苹果文档,

范围0是完全匹配的范围,肯定可以获得。

那么ranges数组中从第1个到第(numberOfRanges - 1)个的值就是段,对应正则匹配的每个段的结果。

使用之前给出的NSRange 的substring 方法,您可以使用range 来检索匹配的结果。

OC代码

对于匹配中的匹配{

让stringToFormat=text.substring(with: match.rangeAt(2))!

切换text.substring(with: match.rangeAt(1))! {

案例“*”:

print("设为粗体: "(stringToFormat)"")

案例“_”:

print("设为italic: "(stringToFormat)"")

默认:

休息

}

}

//打印出

//将bold:设为“粗体”

//将italic: 设置为“斜体”

SWIFT代码

对于匹配中的匹配{

让stringToFormat=text.substring(with:match.range(at: 2) )!

切换text.substring(with:match.range(at: 1) )! {

案例“*”:

print("设为粗体: "(stringToFormat)"")

案例“_”:

print("设为italic: "(stringToFormat)"")

默认:中断

}

}

//打印出

//将bold:设为“粗体”

//将italic: 设置为“斜体”

对于基本替换,直接使用stringByReplacingMatches(in:options:range:with:) 方法,该方法是String.replacingOccurences(of:with:options:) 的增强版本。在上面的例子中,使用了不同的正则匹配(粗体、斜体),并使用了不同的替换模板。

在闪回之后,迭代这些匹配结果,这样以后就不会弄乱匹配范围。

var formattedText=文本

格式:

对于匹配inmatches.reversed () {

让template: 字符串

切换text.substring(with:match.range(at:1) ) ? ""{

案例“*”:

模板="$2"

案例“_”:

模板="$2"

默认:break 格式

}

让matchRange=formattedText.range(from:match.range)! //见上文

让替换=miniFormatter.replacementString( for: 匹配, in:

formattedText, offset: 0, template: template)     formattedText.replaceSubrange( matchRange , with: replacement) } // "formattedText" is now: // "MiniFormatter handlesboldanditalictext." 通过自定义的模版,调用 miniFormatter.replacementString(for:in:...)方法, 然后呢,每一个NSTextCheckingResult 实例会随之产生一个对应的替换字符串。

Expression and Matching Options   , 表达式与匹配选项

NSRegularExpression 是高度可配置的。弄一个实例,或者调用执行正则匹配的方法,都可以传不同选项的组合。 NSRegularExpression.Options * .caseInsensitive : 字母大小写忽略。 开启字母大小写忽略的匹配,就是 i 标记 * .allowCommentsAndWhitespace : 允许注释、空格。 忽略 # 和句尾间任意的空格和注释。所以所以你可以尝试格式化和记录正则匹配,有了注释和空格,正则会好读一点。 等价于 x 标记 * .ignoreMetacharacters: 忽略元符号,忽略关键字。String.range(of:options:)方法中的去正则化,与.regularExpression正则选项相反。这实际上就是正则变为简单的文本搜索,忽略所有的正则关键字和运算符。 * .dotMatchesLineSeparators: 句点分行匹配。允许 , 关键字匹配换行符以及其他字符。就是 s 标记。 * .anchorsMatchLines: 句中锚点匹配。允许 ^ (开始)和 $ (结束)关键字,匹配句中的开始和结束。而不仅仅是输入的整段的开始和结尾。就是 m 标记 * .useUnixLineSeparators, .useUnicodeWordBoundaries:  最后两项优化了更多特定的行和字的边界处理。Unix 行分隔符。

NSRegularExpression.MatchingOptions     正则表达式的匹配选项

一个 NSRegularExpression 正则表达式实例中,可以传入选项来调整匹配的方法。 * .anchored:   锚定的。仅匹配搜索范围的开头第一段。 * .withTransparentBounds: 超过界限。允许正则在搜索范围前,向前查找。反之,向后查找。还有单词的边界。(尽管不适用于,实际的匹配字符) static var withTransparentBounds: NSRegularExpression.MatchingOptions Specifies that matching may examine parts of the string beyond the bounds of the search range, for purposes such as word boundary detection, lookahead, etc. This constant has no effect if the search range contains the entire string. See enumerateMatches(in:options:range:using:) for a description of the constant in context. 苹果 链接:  https://developer.apple.com/documentation/foundation/nsregularexpression.matchingoptions * .withoutAnchoringBounds : 无锚定界限。 让 ^ 和 $ 关键字仅匹配字符串的开始和结尾,而不是搜索范围的开始和结束。 * .reportCompletion ( 报告完成 ) , .reportProgress ( 报告进度 ):  这些参数选项仅在下节讲的部分匹配方法中有用。当正则查找完成了,或者是耗时的匹配上有进度,相应选项会通知 NSRegular​Expression 传入附加时间,调用枚举块。

Partial Matching       部分匹配

最后, NSRegular​Expression 最强大的特性之一是,仅扫描字符串中需要的部分。处理长文本,挺有用的。处理耗资源的正则匹配,也是。 不要用这两个方法 firstMatch(in:...)和matches(in:...), 调用 enumerateMatches(in:options:range:using:) ,用闭包处理对应的匹配。 func  enumerateMatches( instring : String, options:NSRegularExpression.MatchingOptions= [], range:NSRange,  usingblock:  (NSTextCheckingResult?,NSRegularExpression.MatchingFlags,UnsafeMutablePointer) ->Void) 苹果链接: https://developer.apple.com/documentation/foundation/nsregularexpression/1409687-enumeratematches 这个闭包接收三个参数,匹配的正则结果,一组标志选项, 一个布尔指针。 这个 bool 指针是一个只出参数,可以通过它在设定的时机停止处理。 可以用这个方法在 Dostoevsky 的 Karamazov 兄弟一书中, 查找开始的几个名字。名字遵从的规则是,首名,中间父姓 ( 例如: “Ivan Fyodorovitch” ) OC 代码 NSString * namePattern = @"([A-Z]\S+)\s+([A-Z]\S+(vitch|vna))"; NSRegularExpression * nameRegex = [NSRegularExpression regularExpressionWithPattern: namePatternoptions: kNilOptionserror: &error]; NSString * bookString = ... NSMutableSet * name = [NSMutableSet set ]; [nameRegex enumerateMatchesInString: bookString options: kNilOptions range: NSMakeRange(0 , [ bookString length ] ) usingBlock: ^( NSTextCheckingResult * result , NSMatchingFlags flags , BOOL * stop ){     if ( result == nil ) return;     NSString * name = [nameRegex replacementStringForResult : resultinString : bookStringoffset : 0 template: @"$1 $2" ];     [names addObject: name ];     // stop once we"ve found six unique names     *stop = ( names.count==6); } ] ; Swift 代码 let nameRegex = try! NSRegularExpression( pattern: "([A-Z]\S+)\s+([A-Z]\S+(vitch|vna))" ) let bookString = ... var names:Set = [] nameRegex.enumerateMatches( in: bookString, range: bookString.nsrange ){     ( result , _ , stopPointer )      in     guard let result = result else { return }     let name = nameRegex.replacementString( for: result , in:  bookString , offset : 0 , template: "$1 $2" )     names.insert(name)     // stop once we"ve found six unique names ,通过 Set 确保,6个不一样的名字文本      stopPointer.pointee = ObjCBool( names.count==6 ) } // names.sorted(): // ["Adelaïda Ivanovna", "Alexey Fyodorovitch", "Dmitri Fyodorovitch", // "Fyodor Pavlovitch", "Pyotr Alexandrovitch", "Sofya Ivanovna"] 通过这种途径,我们只需查找前 45 个匹配,而不是把全书中接近1300个名字都找一遍。性能显著提高。 一旦有所认识,NSRegularExpression 就会超级有用。除了 NSRegularExpression , 还有一个类 NSDataDetector . NSDataDetector 是一个用于识别有用信息的类,可以用来处理用户相关的文本,查找日期,地址与手机号码。通过Fundation 框架处理文本,NSRegularExpression 强大,健壮,有简洁的接口,也有深入 说明: 为了有意思一些, 我采取了意译。并加入了一些 Regex 细节与扩展资料。 文中 出现的 Swift 代码, 已校正到 Swift 4 . 谢谢观看PS: 参考资料 文中的 Swift 代码,github 地址: https://github.com/dengV/regex_001 超好用的正则网站:101

用户评论

麝香味

哇,终于有中文版的 NSHipster 了!

    有17位网友表示赞同!

眷恋

这款 app 太好用了,帮我轻松处理很多字符串问题。

    有20位网友表示赞同!

夏日倾情

之前一直使用英文的 NSHipster,现在有了中文版简直太方便了!

    有9位网友表示赞同!

无望的后半生

NSRegularExpression 真的是很棒工具,中文版应该会有更多的人使用它吧!

    有17位网友表示赞同!

关于道别

终于不用再翻译 NSHipster 了!

    有14位网友表示赞同!

予之欢颜

这个 app 应该早开发出来,学习起来更加容易。

    有12位网友表示赞同!

采姑娘的小蘑菇

对于新手来说,中文版的教程非常友好。

    有18位网友表示赞同!

oО清风挽发oО

可以更快地理解 NSRegularExpression 的用法了。

    有10位网友表示赞同!

千城暮雪

现在开发 iOS 应用更方便了!

    有5位网友表示赞同!

浅巷°

之前总是遇到一些字符串匹配问题,这个 app 太适合我使用了!

    有14位网友表示赞同!

你tm的滚

建议还能加入更多实用案例,帮助学习者更好地掌握工具的使用。

    有10位网友表示赞同!

万象皆为过客

中文版的编写非常仔细,各个细节都很有用。

    有14位网友表示赞同!

清原

学习起来更有兴趣了!

    有15位网友表示赞同!

容纳我ii

希望以后能定期更新 app 的内容,添加最新的技术和特性。

    有7位网友表示赞同!

一生只盼一人

这个 app 值得每个 iOS 开发者使用!

    有20位网友表示赞同!

断秋风

很高兴看到开发者愿意为中文社区贡献力量!

    有9位网友表示赞同!

毒舌妖后

用起来非常流畅,界面设计也很美观。

    有17位网友表示赞同!

失心疯i

希望能有更多类似的中文技术类 App!

    有6位网友表示赞同!

何必锁我心

学习 NSHipster 是 iOS 开发必修课!

    有18位网友表示赞同!

不相忘

强烈推荐给所有 iOS 开发者!

    有15位网友表示赞同!

【NSHipster: NSRegularExpression 中文解析指南】相关文章:

1.蛤蟆讨媳妇【哈尼族民间故事】

2.米颠拜石

3.王羲之临池学书

4.清代敢于创新的“浓墨宰相”——刘墉

5.“巧取豪夺”的由来--米芾逸事

6.荒唐洁癖 惜砚如身(米芾逸事)

7.拜石为兄--米芾逸事

8.郑板桥轶事十则

9.王献之被公主抢亲后的悲惨人生

10.史上真实张三丰:在棺材中竟神奇复活