在看booster内联R的时候,看到过滤R$color这种内部类的时候,是通过正则表达式进行过滤的,然后它的匹配规则是:
|
|
我是想匹配到com/xc/lib/R$color或com/xc/lib/R形如这种class的名字,第一眼看的时候有点懵,然后通过查看正则表达式的语法时候,发现正则是有规律可循的,先看一张表格:
| 符号 | 含义 | 示例 |
|---|---|---|
| . | 匹配任意单个字符(除换行符) | a.b 可匹配 acb、a1b |
| \d | 数字 (0-9) | \d{3} 匹配 123 |
| \D | 匹配非数字 | \d\D 可以匹配9a / 3# / 0F等 |
| \w | 单词字符 (a-z, A-Z, 0-9, _),匹配单词、数字、下划线 | \w+ 匹配 abc_123 |
| \W | 匹配非字母、数字、下划线 | b\Wt 可以匹配b#t / b@t等,但不能匹配but / b1t / b_t等 |
| \s | 空白字符(空格、Tab、换行) | Hello\sWorld 匹配 Hello World |
| \S | 单个非空白字符 | 任意单个非空格字符都匹配 |
| \b | 单词边界 | \bcat\b 仅匹配 cat,不匹配 catalog |
| ^ | 行首 | ^Hello 仅匹配 Hello 在行首的情况 |
| $ | 行尾 | end$ 仅匹配 end 在行尾的情况 |
| * | 匹配前一个字符 0 次或多次 | ab*c 可匹配 ac、abc、abbc |
| + | 匹配前一个字符 1 次或多次 | ab+c 仅匹配 abc、abbc,不匹配 ac |
| ? | 匹配前一个字符 0 次或 1 次 | ab?c 可匹配 ac 或 abc |
| {n} | 匹配 n 次 | a{3} 仅匹配 aaa |
| {n,} | 至少匹配 n 次 | a{2,} 可匹配 aa、aaa |
| {n,m} | 匹配 n 到 m 次 | a{2,4} 可匹配 aa、aaa、aaaa |
| [] | 字符集合 | [aeiou] 匹配任意元音字母 |
| ` | ` | 或(匹配左边或右边) |
| () | 分组 | (ab)+ 匹配 ab、abab |
上面".*/R\\\$.*|.*/R\\.*"可以拆解成两个正则,因为中间用了一个或,分别是.*/R\\\$.*、.*/R\\.*,首先来看.*/R\\\$.*它可以分解成:
| 字符 | 含义 | 匹配字符 |
|---|---|---|
| .* | 表示有0次或多次的单个字符 | com/xc/lib |
| /R | 直接匹配字符 | /R |
| \$ | 这里由于和$有冲突,所以前面加了转义,匹配的是$字符 | $ |
| .* | 和开头的匹配一样,表示有0次或多次的单个字符 | color |
所以最终com/xc/lib/R$color能被匹配到,再来看.*/R\\.*它可以分解成:
| 字符 | 含义 | 匹配字符 |
|---|---|---|
| .* | 表示有0次或多次的单个字符 | com/xc/lib |
| /R | 直接匹配字符 | /R |
| \.* | 这里由于和.有冲突,所以前面加了转义,匹配的是0次或多次的.字符 | . |
所以最终com/xc/lib/R也能被匹配到。
更多正则的匹配:
测试用例:
#key_mmkv_migrate_version# ,正则表达式(#[^#]*[^#\\s]+[^#]*#),使用
|
|
该正则表达式作用:用于匹配 以 # 开头和结尾的内容,并且内容中至少包含 一个非空白的非 # 字符。 正则解析:
| 部分 | 含义 |
|---|---|
| # | 匹配 #(开始) |
| [^#]* | 匹配任意多个非 # 的字符(0 次或多次) |
| [^#\s]+ | 至少匹配 1 个非 # 和非空格的字符(保证内容不是空的) |
| [^#]* | 再次匹配任意多个非 # 的字符(0 次或多次) |
| # | 匹配 #(结束) |
| (…) | 括号用于捕获匹配内容 |
Matcher#replaceAll方法
|
|
会被替换成如下:
<a type="topic" >#key_mmkv_migrate_version#</a>
正则:
<a[^>]*?((>[\s\S]*?</a>)|(/>))
|
|
将string转化成Regex:
|
|
用于 匹配 HTML 标签(包括自闭合 和 **带内容的 … 形式)。 正则解析:
| 部分 | 含义 |
|---|---|
| <a | 匹配 <a(开始的 标签) |
| [^>]*? | 非贪婪匹配 内的所有属性(不包括 >) |
| `((… ) | (/>))` |
| >[\s\S]*? | 情况 ①:匹配 > 后的内容,直到 |
| / > | 情况 ②:匹配 (自闭合标签) |
CharSequence.contains(regex: Regex):
|
|
contains方法表示是否符合这个正则判断。
Regex.find(input: CharSequence, startIndex: Int = 0): MatchResult? Regex.find() 方法用于 查找字符串中第一个匹配的结果,返回 MatchResult?,如果找不到匹配项,则返回 null。 MatchResult.range:表示匹配的索引范围,分别用start和endInclusive来表示范围。 MatchResult.value:表示匹配到的内容
正则:(\\S+)=\"([^\"]+)\"
作用:主要是用来匹配html/xml属性及其值,比如<a type="topic" >#key_mmkv_migrate_version#</a> 能匹配到,它是匹配type="topic"。
正则解析:
| 正则部分 | 作用 |
|---|---|
| (\S+) | 匹配属性名(非空字符 \S,匹配至少一个字符 +) |
| = | 匹配等号(固定字符 =) |
| "([^"]+)" | 匹配属性值(被双引号 " 包裹,内容不含 “) |
Regex.findAll
|
|
用于获取字符串中所有符合正则的结果,返回的是一个Sequence的MatchResult
|
|
MatchResult.destructured属性 用来提取匹配结果的捕获组,例如上面提取的是type和topic这一组内容。
例如:
|
|
然后通过MatchResult.destructured.toList()方法转成list,就可以获取type和topic内容了。
SpannableStringBuilder使用
在 Android 开发中,SpannableStringBuilder 主要用于富文本(Styled Text),可以让字符串的一部分具有不同的格式,比如 颜色、大小、样式、点击事件、图片等。它比 Html.fromHtml() 性能更好,更适合动态拼接文本。
使用:
|
|
- SpannableStringBuilder(“Hello, Android!”) 创建一个可变的 Spannable 对象。
- setSpan(ForegroundColorSpan(Color.RED), 7, 14, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
- ForegroundColorSpan(Color.RED) → 设置前景色为红色。
- 7, 14 → 应用范围(“Android” 字符的索引)。
- SPAN_EXCLUSIVE_EXCLUSIVE → 该 Span 只作用于当前字符范围,后续文本修改不会继承。
- textView.movementMethod = LinkMovementMethod.getInstance(),设置 TextView 可点击
所以如果想要多个效果,可以添加多个span给SpannableStringBuilder,通过多次调用setSpan方法,然后设置不同的坐标信息。
SpannableStringBuilder.append(),可以追加多个span的样式,如下:
|
|
上面用到了SpannableString,它是实现了CharSequence,是对字符串进行样式的扩展类,然后把它添加到SpannableStringBuilder中。
span中插入图片,通过imageSpan实现:
|
|