原文:https://www.cnblogs.com/tomcatandjerry/p/13364566.html
博主没有排版,我自己排了下,如有侵权请联系我
字符种类
部分使用频率几乎为 0 的这里不会提及(比如 \x 之流)
普通
含义 | 助记 | |
---|---|---|
\s | 非空白 | space |
\s | 空白 | |
\d | 数字 | digit |
\D | 非数字 | |
[] | 自定义字符种类可使用 ^ | && 随意组合 |
特别
含义 | 助记 | |
---|---|---|
\h | 横向字符 | horizontal |
\h | 非横向字符 | |
\v | 纵向字符(比如说换行符) | vertical |
\V | 非纵向字符 | |
\w | 单词字符(包括 - _) | word |
\W | 非单词字符 | |
\p{XXX} | POSIX,这个并不常用,在有些时候会方便,Character 有很多 is开头的方法,将方法名中的is 替换为Java 可直接使用进行字符匹配:\p{javaLowerCase} | posix |
\Q | 字符转义开始符 | |
\E | 字符转义结束符,这两个符号之间的内容全部按照字面量处理,里面是所有字符都不会有什么含义,比如 . 就是 .,\s 必须匹配\s,而不是匹配空白。 |
量词
含义 | 助记 | |
---|---|---|
? | 0个或者1个 | |
* | 0个或多个 | |
+ | 1个或多个 | |
{m} | m个 | |
{m,n} | 介于m~n个之间 |
?
修饰在量词之后,表尽可能少的匹配!
边界
普通
含义 | 助记 | |
---|---|---|
^ | 字符开始位置 | |
$ | 字符结束位置 |
特别
含义 | 助记 | |
---|---|---|
\b | 单词边界,单词的最前面和最后面 | |
\B | 非字符串边界 |
下面的内容普通人基本上就已经不管了!
分组捕获
正则表达式中,每出现一对括号就是新建了个新的组。比如:(\\w+)|(\\d+)
正则表达式的组可以用使用索引进行引用,形式为:$index
$0
默认指向原来的全部字符
然后索引递增规律如下:
((a)|(bc))
$1
指向 ((a)|(bc))
匹配的内容
$2
指向 (a)
匹配的内容
$3
指向 (bc)
匹配的内容
然而当正则复杂之后,改动将会对索引有较大影响,也不方便计算索引,此时,你可以为组制定名称:
比如匹配字符串:a=123,b=456
中间的键值,使用索引,需要写成:(\\w+)=(\\S+)
,然后使用$1
指向 key,使用 $2
指向 value。
我们可以将正则改为:(?<key>\\w+)=(?<value>\\S+)
,上述表达式使用 ?<name>
的形式在正则中为组定义名称。
引用分组
在 Java 中,你可以在两种地方使用引用:
- 正则表达式中
匹配 xxx-xxx
字符 -
两边的内容相同,使用索引引用前面的组(\\index
):
(\\w+)-\\1
使用名字引用前面的组:
(?<content>\\w+)-\\k<content>
- 在 Java 的字符串替换中
Markdown 中的字符串转为斜线的html:
"*name*".replaceAll("\\*(?<content>\\w+)\\*", "<em>$1</em>")
"*name*".replaceAll("\\*(?<content>\\w+)\\*", "<em>${content}</em>")
模式
你可以在构造 Pattern
时设定模式:
Pattern.compile("abc", Pattern.CASE_INSENSITIVE)
模式可以自行到 Pattern
下查看,这里只说使用方式,在组开头使用 ?flags:
的方式声明模式,比如:
匹配单词,不区分大小写
(?i:\\w+)
记住i
(忽略大小写)、s
(. 匹配全部字符)即可,其他基本不用。
前瞻后顾
前瞻后顾,是正则表达式中的高级技巧,主要有5种:
注意:虽然这货也有括号,但是这货只算个条件,并不会捕获任何内容,也不会影响索引
前瞻
前瞻中不带<
,并且只影响前面的表达式,意思就是偷偷往前看一下(这看一下没有限制的,可以看到结尾)。
exp1(?=exp2)
寻找后面是 exp2 的 exp1
exp1(?!exp2)
后顾
(?<=exp1)exp2
匹配 exp1 后面的 exp2,前面没有exp1的内容将被忽略,比如,替换abcba
替换c
后面的b
为 xxx
,需要写为:
"abcba".replaceAll("(?<=c)b", "xxx")
a
后面的b
则不受影响。
注意:正则表达式
(?<=c)b
不会匹配字符串cb
,意思就是:assertFalse("cb".matches("(?<=c)b")); assertFalse("b".matches("(?<=c)b")); assertTrue("cb".matches("c(?<=c)b"));
(?<!exp1)exp2
后顾中带有 <
,并且只影响后面的表达式,也就是说,你如果写成这样:exp2(?<=exp1)
,是没什么卵用的。
以下内容来自另一篇文章
原文链接:https://blog.csdn.net/handsomexiaominge/article/details/87886857
非获取匹配
当我们使用正则表达式的时候,捕获的字符串会被缓存起来以供后续使用,具体表现为每个()中的表达式所匹配到的内容在进行正则匹配的过程中,都会被缓存下来,如以下代码
var testReg=/(a+)(b*)c/;
testReg.test('aaaabbbccc');//输出true
console.log(RegExp.$1);//输出aaaa
console.log(RegExp.$2);//输出bbb
但是,如果在子分组中加入?:之后,分组依然成立,但是不会被缓存下来,看以下代码
var testReg=/(a+)(?:b*)c/;
testReg.test('aaaabbbccc');//输出true
console.log(RegExp.$1);//输出aaaa
console.log(RegExp.$2);//输出""
断言
我们知道,正则表达式中大部分的结构所匹配的文本最终会出现在匹配结果中,但也有一部分结构并不真正匹配文本,而只是负责判断某个位置左/右侧是否符合要求,这种结构被称为断言
常用的断言有以下四种
(?=pattern) | 非获取匹配,正向肯定预查,在任何匹配pattern的字符串开始处匹配查找字符串,该匹配不需要获取供以后使用。 |
(?!pattern) | 非获取匹配,正向否定预查,在任何不匹配pattern的字符串开始处匹配查找字符串,该匹配不需要获取供以后使用。 |
(?<=pattern) | 非获取匹配,反向肯定预查,与正向肯定预查类似,只是方向相反。 |
(?<!patte_n) | 非获取匹配,反向否定预查,与正向否定预查类似,只是方向相反。 |
牛刀小试
以下所有内容只能使用String#repalceAll
或者String#matches
完成。
手机号遮罩
将11
位手机号除前4位之外,其他的使用*
替换。
格式化数字
例如:1234567890
使用正则替换之后,变为 1,234,567,890
。
Trim 字符串
使用正则去除字符串开始和结束的空白字符。
去除数字结尾的0
1234.4500
应该处理为1234.45
,1234.00
应该处理为1234
。
处理文档
将字符串的* 测试 * ** 测试 **
的使用单个*
包围的内容两边分别加上<h1>
、</h1>
,不能影响两个**
包围的内容。
测试某个字符串是不是合法的Java标识符
测试IPv4
已知IPv4
中每一段的数字需要介于0~255,测试某个字符串是否是合法的IPv4
表达式。
去除//
注释
已知Java
中可以使用//
进行单行注释,请去除一段代码中的这种注释。
去除/* 内容 */
注释
已知Java
中可以使用/* */
进行多行注释,请去除代码中的这种注释。