参考:正则表达式、正则表达式30分钟入门教程、正则表达式的使用方法
一、概述
正则表达式(Regular Expression)是一种文本模式,包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为“元字符”)。
正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串。
正则表达式是繁琐的,但它是强大的,学会之后的应用会让你除了提高效率外,会给你带来绝对的成就感。
二、简介
除非您以前使用过正则表达式,否则您可能不熟悉一些术语。但是,毫无疑问,您已经使用过不涉及脚本的某些正则表达式概念。
例如,您很可能使用?
和*
通配符来查找硬盘上的文件。?
通配符匹配文件名中的0个或单个字符,而 *
通配符匹配零个或多个字符。像 data?.dat
这样的模式将查找下列文件:
data1.dat
data2.dat
datax.dat
dataN.dat
使用*
字符代替 ?
字符扩大了找到的文件的数量。data*.dat
匹配下列所有文件:
data.dat
data1.dat
data2.dat
data12.dat
datax.dat
dataXYZ.dat
ps:在OC中的结果,
`data?.dat `匹配
dat.dat
data.dat
datfdat
datagdat
`data*.dat `匹配
dat.dat
data.dat
dataa.dat
dataaa.dat
datfdat
datagdat
datahdat
我主要想说明的是.匹配任意字符
*匹配的是数量上0个或者多个(也就是说,可以没有,可以有一个,也可以有多个)
?匹配的是数量上0个或者是1个(也就是可以也可以没有)
尽管这种搜索方法很有用,但它还是有限的。通过理解 * 通配符的工作原理,引入了正则表达式所依赖的概念,但正则表达式功能更强大,而且更加灵活。
正则表达式的使用,可以通过简单的办法来实现强大的功能。下面先给出一个简单的示例:
^[0-9]+abs$
-
^
为匹配输入字符串的开始位置。 -
[0-9]+
匹配多个数字,[0-9]
匹配单个数字,+
匹配一个或者多个。 -
abc$
匹配字母 abc 并以 abc 结尾,$ 为匹配输入字符串的结束位置。
示例:
匹配以数字开头,并以abc结尾的字符串。:
var str = "123abc";
var patt1 = /^[0-9]+abc$/;
document.write(str.match(patt1));
以下标记的文本是获得的匹配的表达式:
123abc
ps:这只是在文件搜索系统中的正则看,在iOS中则略有不同,所以不要在OC中测试上述正则
为什么要使用正则表达式?
典型的搜索和替换操作要求您提供与预期的搜索结果匹配的确切文本。虽然这种技术对于静态文本执行简单的搜索和替换任务已经足够了,但它缺乏灵活性,若采用这种方法搜索动态文本,即使不是不可能,至少也会变得很困难。
通过正则表达式,可以:
测试字符串内的模式:
例如,可以测试输入字符串,以查看字符串是否出现电话号码模式或信用卡号码模式。这称为数据验证。替换文本。
可以使用正则表达式来识别文档中的特定文本,完全删除该文本或者用其他文本替换它。基于模式匹配从字符串中提取子字符串。
可以查找文档内或者输入域内特定的文本。
例如,您可能需要搜索整个网站,删除过时的材料,以及替换某些HTML格式标记。在这种情况下,可以使用正则表达式来确定在每个文件中是否出现该材料或该HTML格式标记。此过程将受影响的文件列表缩小到包含需要删除或更改的材料的那些文件。最后,可以通过正则表达式来搜索和替换标记。
三、正则表达式的语法
下面描述了正则表达式用于匹配字符串中的模式的字符表达式,制定模式匹配多少次的模式运算符和其他匹配限制,最后一个表指定可以包含在正则表达式中的标志通过多行指定搜索行为的模式(也可以使用选项标志来指定这些标志)
表1描述了用于匹配字符串中的字符的字符序列
表格1正则表达式元字符
字符表达 | 描述 |
---|---|
\a | 匹配BELL, \u0007 |
\A | 在输入开始时匹配。不同于^在\A输入中的一个新行之后将不匹配。 |
\b, outside of a [Set] | 如果当前位置是字边界匹配。边界发生word(\w)和非word(\W)字符之间的转换处,组合标记被忽略。为了更好的字边界,请参阅。NSRegularExpressionUseUnicodeWordBoundaries |
\b, within a [Set] | 匹配退格,\u0008。 |
\B | 如果当前位置不是字边界匹配。 |
\cX | 匹配一个control-X字符 |
\d | 匹配任何字符与Unicode通用类别的Nd(数字,十进制数字) |
\D | 匹配任何不是十进制数字的字符。 |
\e | 匹配ESCAPE,\u001B。 |
\E | 终止\Q ... \E引用的序列。 |
\f | 匹配一个form feed,\u000C。 |
\G | 如果当前位置在上一个匹配结束时匹配。 |
\n | 匹配LINE FEED,\u000A。 |
\N{UNICODE字符名称} | 匹配named character。 |
\p{UNICODE PROPERTY NAME} | 使用指定的Unicode属性匹配任何字符。 |
\P{UNICODE PROPERTY NAME} | 匹配任何不具有指定Unicode属性的字符。 |
\Q | 行情所有后续字符,直到\E。 |
\r | 匹配运送返回,\ u000D。 |
\s | 匹配一个空白字符。空格被定义为[\ t \ n \ f \ r \ p {Z}]。 |
\S | 匹配非空白字符。 |
\t | 匹配水平制表符,\u0009。 |
\uhh | 匹配字符与十六进制值hh |
\Uhhhhhhhhh | 匹配字符与十六进制值hhhhhhhhhh。必须提供8位十六进位数字,即使是最大的Unicode代码点\U0010ffff |
\w | 匹配一个字符 字符是[\ p {L1} \ p {Lu} \ p {Lt} \ p {Lo} \ p {Nd}]。 |
\W | 匹配非字词。 |
\x{hhhh} | 匹配字符与十六进制值hhhh。可提供1到6个十六进制数字。 |
\x | 匹配字符与两位十六进制值hh |
\X | 匹配一个化身集群 |
\Z | 如果当前位置在输入结束处,而在最后一行终止符之前,则匹配,如果存在。 |
\z | 如果当前位置在输入结束时匹配。 |
\n | 返回参考。匹配任何第n个捕获组匹配。n必须是模式中的数字≥ 1和≤总数量的捕获组。 |
\0ooo | 匹配八进制字符 ooo是从一到三个八进制数字。0377是最大允许的八进制角色。领先的零是必需的; 它将八进制常数与反向引用区分开来。 |
[pattern] | 匹配模式中的任何一个字符。 |
. | 匹配任何角色 见并且在字符表达式表4。NSRegularExpressionDotMatchesLineSeparators |
^ | 在一行开始匹配 见并且在字符表达式表4。NSRegularExpressionAnchorsMatchLines\m |
$ | 在一行结束时匹配。见并且在字符表达式表4。NSRegularExpressionAnchorsMatchLines |
引用以下字符。必须引用被视为文字的字符是* ? + [ ( ) { } ^ $ | \ . / |
正则表达式运算符
表2正则表达式运算符
操作 | 描述 | ||
---|---|---|---|
交替 (甲 | 乙)要么匹配甲或乙。 | ||
* | 0或者是更多次数的匹配 | ||
+ | 1或更多次 匹配尽可能多的次数。 | ||
? | 匹配零次或一次 | ||
{n} | 完全匹配n次 | ||
{n,} | 至少匹配n次 匹配尽可能多的次数。 | ||
{n ,m} | n和m之间的匹配。匹配尽可能多的次数,但不能超过m。 | ||
*? | 匹配0或更多次 匹配尽可能少的次数。 | ||
+? | 比赛1次以上 匹配尽可能少的次数。 | ||
?? | 匹配零次或一次。更偏好零。 | ||
{n}? | 完全匹配n次 | ||
{n,}? | 匹配至少n次,但不超过整体模式匹配所需。 | ||
{n,m}? | n和m之间的匹配。匹配次数尽可能少,但不小于n。 | ||
*+ | 匹配0次以上。在第一次遇到时,尽可能多地匹配,即使整体匹配失败(Possessive Match)也不要重试。 | ||
++ | 匹配一次以上 possessive match | ||
?+ | 匹配零次或一次。possessive match | ||
{n}+ | 完全匹配n次 | ||
{n,}+ | 至少匹配n次possessive match | ||
{n,m}+ | n和m之间的匹配次数,possessive match | ||
(...) | 捕获括号。匹配圆括号子表达式的输入范围在匹配后可用 | ||
(?:...) | 非捕获括号。对包含的模式进行分组,但不提供匹配文本的捕获。比捕捉括号更有效率。 | ||
(?>...) | 原子匹配括号。括号子表达式的第一个匹配是唯一一个尝试; 如果它不会导致整体模式匹配,请在“ (?>” 之前的位置备份搜索匹配 | ||
(?# ... ) | 自由格式的评论(?# comment )。 | ||
(?= ... ) | 先行断言 如果括号内的图案在当前输入位置匹配,但不会提前输入位置,则为真。 | ||
(?! ... ) | 负面的预言断言。如果括号中的图案在当前输入位置不匹配,则为真。不提高输入位置。 | ||
(?<= ... ) | 瞻性断言 如果括号中的模式与当前输入位置之前的文本匹配,则匹配的最后一个字符就是当前位置之前的输入字符。不改变输入位置。由look-behind模式匹配的可能字符串的长度不能是无限制的(否*或+运算符。 | ||
(?<! ... ) | 负面看法断言。如果括号中的模式与当前输入位置之前的文本不匹配,则匹配的最后一个字符就是当前位置之前的输入字符。不改变输入位置。由look-behind模式匹配的可能字符串的长度不能是无限制的(否*或+运算符。) | ||
(?ismwx-ismwx: ... ) | 标志设置。使用指定的启用或禁用的标志来评估括号中的表达式。标志在标志选项中定义。 | ||
(?ismwx-ismwx) | 标志设置。更改标志设置。更改适用于设置后的模式部分。例如,(?i)更改为不区分大小写的匹配。标志在标志选项中定义。 |
模板匹配格式
本类提供了使用模板匹配的技术既可变和不可变的字符串查找和替换的方法。表3描述了语法。
表3模板匹配格式
字符 | 描述 |
---|---|
$n | 捕获组n的文本将被替换为$ n。n必须>= 0和不大于捕获组的数量。一个$没有后面的数字没有什么特别的意义,并且会以替代文本的形式出现在自己身上$。 |
将以下字符视为文字,抑制任何特殊含义。替换文本中的反斜杠转义只适用于'$'和'',但可以用于任何其他字符而不会产生不良影响。 |
替换字符串被视为模板,$0被匹配范围$1的内容,第一个捕获组的内容替换,等等。除了表示捕获组数量所需的最大值之外的其他数字将被视为普通字符,$不会跟随数字。反斜杠将难逃都$和\
标记选项
以下标志控制正则表达式匹配的各个方面。
可以使用(?ismx-ismx)模式选项在模式中指定这些标志值。当使用选项标志初始化时,可以为整个模式指定等效的行为。
NSRegularExpressionNSRegularExpressionOptions
表4 标记选项
flag(pattern) | 描述 |
---|---|
i | 如果设置,匹配将以不区分大小写的方式进行。 |
X | 如果设置,允许在模式中使用空格和#comments |
s | 如果设置,.模式中的“ ”将匹配输入文本中的行终止符。默认情况下,它不会。请注意,carriage-return / line-feed pair文本中的内容表现为单行终止符,并将匹配.正则表达式模式中的单个“ ” |
m | 以模式控制“ ^”和“ $” 的行为。默认情况下,这些仅分别匹配输入文本的开始和结束。如果设置了这个标志,“ ^”和“ $”也将在输入文本的每一行的开头和结尾相匹配。 |
w | 控制模式中的行为\b。如果设置,则根据Unicode UAX 29“文本边界”中发现的词的定义找到字边界。默认情况下,通过将字符简单地分类为“单词”或“非单词”来识别字边界,其近似于传统的正则表达行为。使用两个选项获得的结果在空格和其他非字符字符的运行中可能会有很大差异。 |
性能
NSRegularExpression
实现了非确定性有限自动机匹配引擎。因此,当尝试执行匹配时,包含多个*或+运算符的复杂正则表达式模式可能会导致较差的性能 -特别是无法匹配给定的输入。有关更多信息,请参阅“ICU用户指南”的“性能提示”部分。
四、OC中的Regular表达式NSRegularExpression
NSRegularExpression被设计为不可变的和线程安全的,因此可以一次使用单个实例来匹配多个线程上的操作。但是,在匹配操作的过程中,无论是从另一个线程还是在迭代中使用的块内,不应该在其上操作它的字符串。
1、创建正在表达式
+ regularExpressionWithPattern:options:error:使用指定的正则表达式模式和选项创建一个NSRegularExpression实例。
- initWithPattern:options:error:
返回具有指定的正则表达式模式和选项的初始化NSRegularExpression实例。
2、获取正则表达式和选项
pattern
返回正则表达式模式。options
返回创建正则表达式选项时使用的选项。numberOfCaptureGroups
返回正则表达式中捕获组的数量。
3、使用正则表达式搜索字符串
- numberOfMatchesInString:options:range:
返回字符串指定范围内正则表达式的匹配数。- enumerateMatchesInString:options:range:usingBlock:
枚举允许Block处理每个正则表达式匹配的字符串。- matchesInString:options:range:
返回一个数组,其中包含字符串中正则表达式的所有匹配项。
- firstMatchInString:options:range:
返回字符串指定范围内正则表达式的第一个匹配项。
-
- rangeOfFirstMatchInString:options:range:
返回字符串指定范围内正则表达式的第一个匹配的范围。
4、使用正则表达式替换字符串
- replaceMatchesInString:options:range:withTemplate:
使用模板字符串替换可变字符串中的正则表达式匹配。- stringByReplacingMatchesInString:options:range:withTemplate:
返回包含与模板字符串替换的匹配正则表达式的新字符串。
5、在字符串中转义
+ escapedTemplateForString:
通过根据需要添加反斜杠转义来返回模板字符串,以保护符合模式元字符的任何字符+ escapedPatternForString:
通过根据需要添加反斜杠转义来返回字符串,以保护符合模式元字符的任何字符。
6、自定义替换功能
-
- replacementStringForResult:inString:offset:template:
用于为实现自己的替换功能的客户端执行单个结果的模板替换。
7、常数
NSRegularExpressionOptions
这些常量定义正则表达式选项。
这些常数被 options,和regularExpressionWithPattern:options:error:
initWithPattern:options:error:NSMatchingFlags
由块匹配进行设置,完成或失败。
用于该方法
enumerateMatchesInString:options:range:usingBlock:
NSMatchingOptions
匹配选项常量指定表达式匹配方法的报告,完成和匹配规则。
所有使用正则表达式搜索或替换值的方法都使用这些常量。
五、optionals
1、NSMatching 选项
匹配选项常量指定表达式匹配方法的报告,完成和匹配规则。所有使用正则表达式搜索或替换值的方法都使用这些常量。
NSMatchingReportProgress在长时间运行的匹配操作中定期调用Block。此选项对于除此以外的方法没有影响。请参阅上下文中常量的描述。enumerateMatchesInString:options:range:usingBlock:
enumerateMatchesInString:options:range:usingBlock:NSMatchingReportCompletion
完成任何匹配后,调用Block一次。此选项对于除此以外的方法没有影响。请参阅上下文中常量的描述。enumerateMatchesInString:options:range:usingBlock:
enumerateMatchesInString:options:range:usingBlock:
NSMatchingAnchored
指定匹配仅限于搜索范围开始时的匹配。请参阅上下文中常量的描述。NSMatchingWithTransparentBounds
指定匹配可以检查超出搜索范围的范围的字符串的部分,以用于诸如字边界检测,前瞻等。如果搜索范围包含整个字符串,该常量将不起作用。
请参阅上下文中常量的描述。NSMatchingWithoutAnchoringBounds
指定^并且$不会自动匹配搜索范围的开始和结束,但仍将与整个字符串的开头和结尾相匹配。如果搜索范围包含整个字符串,则该常量不起作用。请参阅上下文中常量的描述。 enumerateMatchesInString:options:range:usingBlock:
2、NSRegular表达式选项
NSRegular Expression Case Insensitive
匹配字母在模式中独立于案例。NSRegular Expression Allow Comments And Whitespace
在模式中忽略空格和#-prefixed注释。NSRegular Expression Ignore Metacharacters
将整个图案视为文字字符串。NSRegular Expression Dot Matches Line Separators
允许.匹配任何字符,包括行分隔符。NSRegular Expression Anchors Match Lines
允许^和$匹配行的开始和结束。NSRegular Expression Use Unix Line Separators
仅将\n
视为行分隔符(否则,将使用所有标准行分隔符)。NSRegular Expression Use Unicode Word Boundaries
使用Unicode TR#29来指定字边界(否则,使用传统的正则表达式字边界)。
五、正则表达式的使用
1、谓词(NSPredicate)创建正则表达式
使用它来判断用户输入的字符串是否为合法的:
// 编写正则表达式:只能是数字或英文,或两者都存在
NSString *regex = @"^[a-z0-9A-Z]*$";
// 创建谓词对象并设定条件的表达式
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];
// 判断的字符串
NSString *str = @"Hello100";
// 对字符串进行判断
if ([predicate evaluateWithObject:str]) {
NSLog(@"Match");
}
2、NSString实例方法
使用rangeOfString:options:方法可以做到,具体看例子:
NSString *phoneNo = @"13143503442";
NSRange range = [phoneNo rangeOfString:@"^1[3]\\d{9}$" options:NSRegularExpressionSearch];
if (range.location != NSNotFound) {
NSLog(@"%@", [phoneNo substringWithRange:range]);
}
rangeOfString:options:会返回一个NSRange,用来接收匹配的范围,当匹配不到结果时,将会返回一个NSIntegerMax最大值,也就是NSNotFound,因此我们可以用它来判断用户输入的内容是否符合规则。
3、NSRegularExpression类创建正则表达式
我们可以使用正则来过滤并获取我们想要的特定部分,实现方法也很简单,可以用到NSRegularExpression这个类实现:
NSString *url = @"1229436624@qq.com";
NSError *error;
// 创建NSRegularExpression对象并指定正则表达式
NSRegularExpression *regex = [NSRegularExpression
regularExpressionWithPattern:@"[^@]*\\."
options:0
error:&error];
if (!error) { // 如果没有错误
// 获取特特定字符串的范围
NSTextCheckingResult *match = [regex firstMatchInString:url
options:0
range:NSMakeRange(0, [url length])];
if (match) {
// 截获特定的字符串
NSString *result = [url substringWithRange:match.range];
NSLog(@"%@",result);
}
} else { // 如果有错误,则把错误打印出来
NSLog(@"error - %@", error);
}
这个例子是从字符串里检索出以“@”开头“.”结尾的区间字符串,最后检索出来的字符串结尾包括“.”,因此此例子最终输出结果为“qq.”
4、NSRegularExpression类之抓取多个结果
当一个字符串有多个符合特定规则的字符,我们可以分别获取到符合特定规则的字符:
NSString *regex = @"\\-\\d*\\.";
NSString *str = @"-34023242.-34203020.";
NSError *error;
NSRegularExpression *regular = [NSRegularExpression regularExpressionWithPattern:regex
options:NSRegularExpressionCaseInsensitive
error:&error];
// 对str字符串进行匹配
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);
}
从指定字符串中获取以“-”开头以“.”结尾的字符,因为可能有多个符合特定规则的字符串,因此我们需要把它们遍历出来,具体输出结果如下
017-05-02 16:38:52.309 Juny_regularDemo[1669:190937] -34023242.
2017-05-02 16:38:52.310 Juny_regularDemo[1669:190937] -34203020.
总结:一般来说,判断用户输入的是否合法,只需要方法一就可以了。如果是需要捕获用户输入的特定内容,可以用方法二或者方法三、四,如果可能有多个捕获结果,那么可以使用方法四,否则使用方法二。