ios技巧 -- 正则与lldb
Regular Expressions
正则表达式:是处理字符串的⼀种表达⽅式。提供了⼀种从⼀组字符串中
选择特定字符串的机制。
POSIX规范定义了UNIX操作系统应当⽀持的功能,POSIX规范的正则表达
式:
-
BRE
(Basic Regular Expression,基本型正则表达式) -
ERE
(Extended Regular Express,扩展型正则表达式)
BRE
和ERE
⼆者的区别,简单的说就在于(、)、{、}、+、?、|这7个特殊字符的使⽤⽅法上:
- 在BRE中如果想要这些字符表示特殊的含义,就需要把它们转义。元字符 (、)、{、}、 +、?、| 必须转义之后才具有特殊含义,如+、?、|,⽽且也⽀持\1、\2之类反向引⽤。
- 反之,在ERE中如果要这些字符不表示特殊的含义,就需要把它们转义。虽然BRE名为“基本”⽽ERE名为“扩展”,但ERE并不要求兼容BRE的语法,⽽是⾃成⼀体。
- BRE中的特殊字符:.、\、[、^、$、*。
- ERE中的特殊字符多了7个,即:.、\、[、^、$、*、(、)、{、}、+、?、|。
正则表达式与通配符没有任何关系,不是包含关系!
- 通配符,是Shell提供的功能
- 正则表达式只是⽤来处理字符串
重复操作符:
类别 | 匹配类型 |
---|---|
* | 匹配前⼀个元素0次或多次 |
+ | 匹配前⼀个元素1次或多次 |
? | 匹配前⼀个元素0次或1次 |
间隔操作符( { … } ):
类别 | 匹配类型 |
---|---|
{count} | 匹配前⼀个元素count次 |
{min,} | 匹配前⼀个元素⾄少min次 |
{min, max} | 匹配前⼀个元素⾄少min次,⾄多max次 |
备胎操作符:
类别 | 匹配类型 | 匹配字符 |
---|---|---|
| | 匹配前⼀个表达式或后⼀个表达式 在吗? | 我怀孕了 |
列表操作符( [ ... ] and [^ ... ] ):
⼀般操作符在列表操作符⾥会失去特殊意义,除了:
类别 | 匹配类型 |
---|---|
] | 结束列表。[]] |
\ | 转义字符 |
[: | 字符类别操作符开始 |
:] | 字符类别操作符结束 |
- | 范围操作符,0-9 |
字符类别操作符( [: … :] ):
类别 | 匹配类型 | 匹配字符 |
---|---|---|
[:alnum:] | [A-Za-z0-9] | 数字和字⺟字符 |
[:alpha:] | [A-Za-z] | 字⺟字符 |
[:blank:] | [ \t] | 空格和TAB |
[:cntrl:] | [\x00-\x1F\x7F] | 控制符 |
[:digit:] | [0-9] | 数字 |
[:graph:] | [\x21-\x7E] | 可视字符 |
[:lower:] | [a-z] | ⼩写字⺟字符 |
[:print:] | [\x20-\x7E] | 可视字符和空格(ASCII, |
[:punct:] | ][!"#$%&'()*+,./:;<=>?@^_`{|}~-] 040-0176) | 标点符号 |
[:space:] | [\t\r\n\v\f] | 空⽩字符 |
[:upper:] | [A-Z] | ⼤写字⺟字符 |
[:xdigit:] | [A-Fa-f0-9] | ⼗六进制字符 |
特殊字符类别操作符:
类别 | 匹配类型 | 匹配字符 |
---|---|---|
\w | [:alnum:] | 数字和字⺟字符 |
\d | [:digit:] | 数字 |
\W | [^[:alnum:]] | 除了数字和字⺟字符 |
\B | [^[:digit:]] | 除了数字 |
< | ^ | 匹配字符串的开头 |
> | $ | 匹配字符串的结尾 |
\b | 匹配单词边界字符,to\b匹配to!,但不匹配tomorrow |
范围操作符:
类别 | 匹配类型 |
---|---|
- | 匹配指定范围,但是需在列表中使⽤,并指定范围,如[a-z]。[-az]或者[az-]表示匹配字⺟a和z还有- |
分组\捕获组操作符 (( ... ) or ( ... )):
定义⼀个⼦表达式。正则表达式将此序列视为⼀个单元。圆括号在整体匹配完后进⾏匹配。
可以配合反向引⽤操作符,重复使⽤分组匹配的结果。
反向引⽤操作符 (( \digit ) :
反向引⽤操作符由`\数字' 表示,数字需介于1-9,代表引⽤那个分组的匹配结果。
锚点操作符:
类别 | 匹配类型 |
---|---|
^ | 匹配字符串的开头,需在开头 |
$ | 匹配字符串的结尾或者换⾏符的前⼀个位置,需在结尾 |
注意⚠:如果^在列表操作符中使⽤,并且在⾸位,代表取反。
操作符优先级:
优先级(由⾼到低) | 操作符 |
---|---|
归类相关的括号符号 | [::] |
转义字符 | <特殊字符> |
括号表达 | [] |
分组 | () |
单字符重复 | * + ?{m, n} |
串联 | . |
锚点 | ^ $ |
备选 | | |
Objective-C
和Swift
都要求您转义⽂字字符串中的特殊字符(即,在它们
前⾯加反斜杠\字符)。反斜杠本身就是这样的特殊字符之⼀!由于⽤于创建
正则表达式的模式也是字符串,因此会增加复杂性,因为在使⽤Stringand
时
需要转义反斜杠字符NSRegularExpression
。
这意味着标准正则表达式.将出现\.在您的Swift(或Objective-C)代码中。
- ⽂字”\.”定义了⼀个类似于以下字符串:.
- 正则表达式.然后将匹配单个句点字符。
贪婪模式、勉强模式与侵占模式:
贪婪匹配 | 勉强匹配 | 侵占匹配 | 作⽤ |
---|---|---|---|
X? | X?? | X?+ | 匹配 X 零次或⼀次 |
X* | X*? | X*+ | 匹配 X 零次或多次 |
X+ | X+? | X++ | 匹配 X ⼀次或多次 |
X{n} | X{n}? | X{n}+ | 匹配 X n 次 |
X{n,} | X{n,}? | X{n,}+ | 匹配 X ⾄少 n 次 |
X{n,m} | X{n,m}? | X{n,m}+ | 匹配 X ⾄少 n 次,但不多于 m 次 |
假定要分析的字符串是xfooxxxxxxfoo
模式.foo(贪婪模式)由两部分:
1.p1(.)
2.p2(foo)组成。 其中p1中的匹配⽅式使⽤默认⽅式(贪婪型)。
第⼀轮:匹配开始时,p1匹配所有字符xfooxxxxxx,匹配成功,但p2⽆匹配字符,本轮匹配失
败;
第⼆轮:减少p1部分的匹配量,留出最后⼀个字符, 此时存在两个字符串,s1代表xfooxxxxxxfo和
s2代表o。 s1匹配p1, 但s2不匹配p2。本轮匹配失败;
第三轮,继续减少p1匹配量,留出两个字符, 字符串被分割成xfooxxxxxxfo和oo两部分。结果同
上。
第四轮,再次减少p1匹配量,字符串分割成xfooxxxxxx和foo两个部分,这次p1/p2同时匹配。
返回匹配成功。
假定要分析的字符串是xfooxxxxxxfoo
模式.?foo(勉强模式)最⼩匹配⽅式:
1.p1(.?)
2.p2(foo)组成。 其中p1中的匹配⽅式使⽤勉强模式匹配。
第⼀轮:p1由于是0或任意次,⾸先匹配0次。所以直接⽤字符串去匹配p2,但p2⽆匹配字符,本轮
匹配失败;
第⼆轮:增加p1部分的匹配量,匹配x, 此时存在两个字符串,s1代表x和s2代表fooxxxxxxfoo。 s1
匹配p1, 但s2不匹配p2。本轮匹配失败;
继续上述匹配直到满⾜p2。
假定要分析的字符串是xfooxxxxxxfoo
.+foo(侵占模式):
1.p1(.+)
2.p2(foo)组成。 其中p1中的匹配⽅式使⽤侵占模式匹配。
匹配开始时读⼊所有字符串,和p1匹配成功,但没有剩余字符串去和p2匹配。匹配失败。
简单地说,贪婪模式和占有模式相⽐,贪婪模式会在只有部分匹配成功的条件下,依次从多到少减
少匹配成功部分模式的匹配数量,将字符留给模式其他部分去匹配; ⽽占⽤模式则是占有所有能匹
配成功部分,绝不留给其他部分使⽤。
更⾼级⽤法——零宽断⾔:
断⾔:在指定位置应该满⾜⼀定的条件。
当捕获组以开头时?=,,表示该组将被⽤作零宽度正预测先⾏断⾔,仅当前⼀个模式与捕获组中的
模式相匹配时才与前⼀个模式匹配。例如,A(?=B)与A匹配,并且,⻢上跟着B。可以匹配AB、
ABB、ACB。
更⾼级⽤法——匹配特定类别的Unicode字符\p{ … }:
\p{L}所有字符,\p{Lu}所有⼩写字符,\p{N}。
\P{}匹配不特定类别的Unicode字符。
grep
grep:
-v:逆转显示
-i:忽略⼤⼩写
-A:向上显示⼏⾏
-B:向下显示⼏⾏
-E:启⽤扩展
—color:显示颜⾊
egrep:grep -E
sed:可以将数据进⾏替换、删除、新增、选取特定内容等功能,⽤作⼀整⾏字符处理。
awk:⽐sed更精准,通常将⼀⾏在切割成相应的字段,再去处理。
LLDB
- 对指定库中的符合指定的正则表达式的函数下断点
(lldb) breakpoint set —func-regex=.—shlib=libfoo.dylib - 对符合指定的正则表达式的符号下断点
(lldb) breakpoint set --func-regex regular-expression - 通过对指定的正则表达式对⽂件内容设置断点
(lldb) breakpoint set --source-pattern-regexp regular-expression --file
SourceFile
例如我们现在在block源码中设置断点
我们知道现在block进行了copy操作。所以我们写成(.*)[B|b]lock(.*)[C|c]opy(.*)
,在断点的时候设置成breakpoint set --func-regex=(.*)[bB]lock(.*)[Cc]opy(.*)
。breakpoint
可以简写为br
,-func-regex
可以简写为-r
, =
可以替换为空格,br set -r (.*)[bB]lock(.*)[Cc]opy(.*)
效果是一样的。br set -r
还可以缩写成rb
,rb (.*)[bB]lock(.*)[Cc]opy(.*)
,我们也可以添加--shlib
指定库中查找rb (.*)[bB]lock(.*)[Cc]opy(.*) --shlib=libsystem_blocks.dylib
。--shlib
缩写-s
。
设置指定文件breakpoint set --source-pattern-regexp=(.*)[bB]lock(.*)[Cc]opy(.*) --file runtime.cpp
->br set -p (.*)[bB]lock(.*)[Cc]opy(.*) -f runtime.cpp
可以通过br list 数字
,数字为每次通过lldb设置断点的输出的第多少条。
—func-regex
是对符号下断点,--source-pattern-regexp
是对内容下断点。
br set -p
没有简写,我们可以在lldb中自己设置。
command alias pb br set -p %1 -f %2
,%1
为第一个参数。另外注意这里要用全称,所以之前写的是错误的需要写成command alias pb breakpoint set -p %1 -f %2
,可以通过help pb
来查看。但只能一次运行的时候有用。