参考:
- https://developer.apple.com/library/ios/documentation/Foundation/Reference/NSRegularExpression_Class/
- http://www.raywenderlich.com/30288/nsregularexpression-tutorial-and-cheat-sheet,RW的教程,错不了
- http://regexpal.com/,一个不错的testing regular的网站
- https://github.com/bendytree/Objective-C-RegEx-Categories
- http://regexkit.sourceforge.net/RegexKitLite/
- https://en.wikipedia.org/wiki/Regular_expression
A regular expression is a simple string that can describe a large number of possibilities in a concise notation. — from raywenderlich
这篇文章前半部主要翻译自RW教程的文章,主要是我自己记录Regular语法之用,另外,RW上面的教程中包含一些很有意思的练习例子,我这里没有包含,可以自己去从原文中查找。文章的后半部分,介绍一些github上面关于正则的流行库。
基本语法
Overall Concepts
1. Literal characters ( 字面量字符 )
这个是最简单的正则表达式类型,非常类似我们经常在文本编辑器中做的”find”操作,就是去文本中直接查找这些字符。当然,跟编程语言中类似,正则语法中也有一些属于保留的关键字符,在某些较为高级的正则技巧中会用到。这些关键字有:“[“, “(“, “)” , “\”, “*”, “+”, “?”, “{“, “}”, “^”, “$”, “.”, “|”, “/“。
如果字符串中要使用这些关键字作为字符,跟编程语言中类似,前面加 \ 符号。而在OC中, \ 符号本身也是属于特殊字符,所以要使用 \\ 才能表示 \ 字符。所以,如果在正则中要表示一个”.” 字面量字符,在正则语法中需要使用 " \. "来表示,而在OC中需要使用字符串 @“\\.” 才行。
2. Capturing parentheses
capturing parentheses 用来对正则的某一部分来进行分组,例如,3 (pm|am) 在正则中即会匹配“3 pm”,也会匹配 “3 am”。pipe字符串( | ) 用来表达OR操作符的含义。
另外,当你需要有选择地匹配某个文本的时候,也可以使用括号来分组。例如 November这个词很多场景下也会使用Nov这种缩写来表示,这个时候可以使用 Nov(emver)? 来表示,即匹配Novement也匹配Nov,?表示括号内的文本是可选择的。
之所以使用 “capturing” 来修饰parentheses,是因为这种语法会capture它匹配的内容,并且正则表达式中的其他部分来reference它。 例如,有个字符串”Say hi to Harry”,我们创建一个搜索替换正则表达式,把任意 (Tom|Dick|Harry) 使用 that guy $1 来替换,我们使用这个正则来处理这个字符串,结果就是 “Say hi to Harry” 会变成 “Say hi to that guy Harry”。
至于 capturing 和 non-capturing groups的区别,(?: ),在括号内添加?:表示该group是non-capturing的,non-capturing的意思是不会在buffer中保留匹配到文本。所以,例如上面的例子中,使用(?:Tom|Dick|Harry)来搜索替换的话, $1 就是一个空字符
3. Character classes
character classes 用来表示一个可能的单字符匹配的集合,character classes出现在中括号之间([和])。例如,t[aeiou] 会匹配 “ta”, “te”, “ti”, “to”, or “tu” 这些字符串,你可以在中括号之间定义任意多的字符,但是需要注意的是这个集合内任意的单字符都会被匹配。
如果是连续的字符串,可以使用 - 来表示,例如匹配100到109, 可以使用10[0-9]来表示。同时还可以用来表示连续的字符,比如[a-d]表示[abcd]。
character classes一般用来包含你想要匹配的字符,但是也可以用字符 ^ 来包含你不想匹配的字符,例如t[^o]用来表示除了to之外的任意t开头的两个字符的字符串。
NSRegularExpressions Cheat sheet
关于正则的语法,可以参考iOS-RW-NSRegularExpression-Cheatsheet这个表格来查询相应的语法点,正则本身的语法并不复杂,但有很多复杂的用法和约定,因此经常查查这个cheat sheet 会很有帮助的。下面对里面的部分语法进行一下解释:
- . 会匹配任意的字符,例如 p.p会匹配 pop, pup, pmp, p@p等等
- \w 匹配任意”word-like”的字符,包括数字,字母,下划线,有点类似代码中变量命名的字符。不会匹配标点符号和其他的符号,例如 hello\w 会匹配 hello_9 和 helloo,但是不会匹配 hello!
- \d 匹配数字,大多数情况下表示[0-9]的意思
- \b 用来匹配单词边界字符,例如空格和标点符号。例如,to\b 会匹配 to the moon中to和to!,但是不会匹配 tomorrow
- \s 匹配空白字符,比如空格,tab符,换行符
- ^ 匹配一行的开头,需要注意的是,这个 ^ 特殊字符跟square brackets[] 中的 ^ 字符含义不一样,在square brackets中是表示不想匹配某些字符的意思。例如,^Hello 会匹配 “Hello there”,但是不会匹配”He said Hello”。
- $ 匹配一行的末尾。例如 the end$ 会匹配 “It was the end” 而不会匹配 “the end was near"
- * 表示匹配它前面的元素0或多次。比如,12*3 会匹配 13, 123, 1223, 1222223等
- + 表示匹配它前面的元素至少1次。比如,12+3 会匹配,123,1223, 1222223等,但是不会匹配 13
- Curly braces {} 包含了最小和最大的匹配次数。例如,10{1,2}1 会匹配101,1001,但是不会匹配10001。He[Ll]{2,}o 会匹配 “HeLLo” 和 “HellLLLllo”,和任意这种“hello”包含很多L的变种。
类库
OC源代码:
- https://github.com/bendytree/Objective-C-RegEx-Categories
- https://github.com/Exile90/ICTextView
swift 2.0版本的正则类库:
- https://github.com/kasei/SwiftRegex
- https://github.com/cezheng/PySwiftyRegex
- https://github.com/johnno1962/SwiftRegex
在iOS中,正则的API是比较简单的,主要是NSRegularExpression类相关的操作, https://github.com/bendytree/Objective-C-RegEx-Categories 这个类库对对应API的封装还是相当不错的,本来想详细介绍一下这个类库的封装,但看了一下源码,似乎能说的并不是特别多,详细用法可以参考github主页上的说明就足够了。