正则表达式语法

正则表达式语法

**在其他的语言中(如Perl),一个反斜杠 \ 就足以具有转义的作用,而在 Java 中正则表达式中则需要有两个反斜杠才能被解析为其他语言中的转义作用。**也可以简单的理解在 Java 的正则表达式中,两个\\代表其他语言中的一个 \,这也就是为什么表示一位数字的正则表达式是 \\d,不过还好,在eclipse中可以把正则表达式直接粘贴到字符串中,eclipse会自动帮我们转义。这样免得我们手动添加转移符。

一个字符串其实就是一个简单的正则表达式,例如 Hello World 正则表达式匹配 “Hello World“ 字符串。
正则表达式的特殊字符字符序列如下

普通字符

字母数字汉字下划线、以及没有特殊定义的标点符号,都是“普通字符”。表达式中的普通字符,在匹配个字符串的时候,匹配与之相同的一个字符

简单的转义字符

正则 描述
\n 匹配换行符
\t 匹配制表符
\\ 匹配\本身
\^,\$,\.,\{,\},\?,\+,\*,|,\[,\] 匹配这些字符本身

宇符边界

序号 字符 描述
1 ^ 匹配输入字符串开始的位置。如果设置了 RegExp 对象的 Multiline 属性,^ 还会与”\n“或”\r“之后的位置匹配。
2 $ 匹配输入字符串结尾的位置。如果设置了 RegExp 对象的 Multiline 属性,$ 还会与”\n“或”\r“之前的位置匹配。
3 \b 匹配一个字边界,即字与空格间的位置。例如,”er\b“匹配”never“中的”er“,但不匹配”verb“中的”er“。

自定义字符集合

序号 匹配单个字符 描述
1 . 匹配除”\r\n“之外的任何单个字符。若要匹配包括”\r\n“在内的任意字符,请使用诸如”[\s\S]“之类的模式。
2 [xyz] 字符集匹配括号里包含的任意一个字符。例如,”[abc]”匹配”plain“中的”a“。
3 [^xyz] 反向字符集匹配括号里未包含的任何一个字符。例如,”[^abc]“匹配”plain“中”p“,”l“,”i“,”n“,但不会匹配a
4 [a-z] 范围字符集匹配指定范围内的任何一个字符。例如,”[a-z]“匹配”a“到”z“范围内的任何一个小写字母。
5 [^a-z] 反向范围字符集匹配不在指定的范围内的任何一个字符。例如,”[^a-z]“匹配任何不在”a“到”z“范围内的任何字符。

标准字符集合

序号 字符组简写形式 描述
1 \d 数字字符匹配。等效于 [0-9]
2 \D 非数字字符匹配。等效于 [^0-9]
3 \s 匹配任何空白字符,包括空格、制表符、换页符等。与 [ \f\n\r\t\v] 等效。
4 \S 匹配任何非空白字符。与 [^ \f\n\r\t\v] 等效。
5 \w 匹配任何的字母,数字,下划线。与”[A-Za-z0-9_]“等效。
6 \W 与任何非单词字符匹配。与”[^A-Za-z0-9_]“等效。

量词

序号 量词 描述
1 ? 匹配前面的子符或子表达**1次或者0次**,例如 zo?匹配z或者zo? 等效于 {0,1}
2 * 匹配前面的字符或子表达式**0次或者多次**。例如,zo* 匹配”z“,”zoo“,”zooo“,...* 等效于 {0,}
3 + 匹配前面的字符或子表达式**1次多次**。例如,”zo+“与”zo“和”zoo“匹配,但与”z“不匹配。+ 等效于 {1,}
4 {n} n 是非负整数。正好匹配 n。例如,”o{2}“与”Bob“中的”o“不匹配,但与”food“中的两个”o“匹配。
5 {n,} n 是非负整数。至少匹配 n。例如,”o{2,}“不匹配”Bob“中的”o“,而匹配”foooood“中的所有 o。”o{1,}”等效于”o+“。”o{0,}“等效于”o*“。
6 {n,m} mn 是非负整数,其中 n <= m匹配至少 n 次,至多 m。例如,”o{1,3}“匹配”fooooood“中的头三个 o。’o{0,1}‘ 等效于 ‘o?‘。注意:您不能将空格插入逗号和数字之间。
7 ? 当此字符紧随任何其他限定符(*+?{n}{n,}{n,m})之后时,匹配模式是”非贪心的”。**”非贪心的”模式匹配搜索到的、尽可能短的字符串而默认的”贪心的”模式匹配搜索到的、尽可能长的字符串。**例如,在字符串”oooo“中,”o+?“只匹配单个”o“,而”o+”匹配所有”o“。

非贪婪匹配量词

当正则表达式中包含能接受重复的限定符时,通常的行为是(在使整个表达式能得到匹配的前提下)匹配尽可能多的字符。以这个表达式为例:a.*b,它将会匹配最长的以a开始,以b结束的字符串。如果用它来搜索aabab的话,它会匹配整个字符串aabab。这被称为贪婪匹配

有时,我们更需要懒惰匹配,也就是匹配尽可能少的字符量词都可以被转化为懒惰匹配模式,只要在它后面加上一个问号?就行了。这样.*?就意味着匹配任意数量的重复,但是在能使整个匹配成功的前提下使用最少的重复。现在看看懒惰版的例子吧:

a.*?b匹配最短的,以a开始,以b结束的字符串。如果把它应用于aabab的话,它会匹配aab(第一到第三个字符)和ab(第四到第五个字符)。

所以,在上面的量词后面都加上问号?,就可以懒惰匹配量词表,如下所示。

懒惰匹配量词 说明
*? 重复任意次,但尽可能少重复
+? 重复1次或更多次,但尽可能少重复
?? 重复0次或1次,但尽可能少重复
{n,m}? 重复n到m次,但尽可能少重复
{n,}? 重复n次以上,但尽可能少重复

分组非捕获分组

列名 列名
() 捕获分组,后面可以使用前向引用来引用
(?:) 非捕获分组

反向引用

序号 反向引用 描述
1 \num 匹配 num,此处的 num 是一个正整数到捕获匹配的反向引用。例如,”(.)\1“匹配两个连续的相同字符。”(a).+\1“匹配axa,abbba等等
2 \n 标识一个八进制转义码或反向引用。如果 \n 前面至少有 n 个捕获子表达式,那么 n 是反向引用。否则,如果 n 是八进制数 (0-7),那么 n 是八进制转义码。
3 $num java中反向引用的写法,用的是美元符号$代替反斜杠\

不可见字符

序号 转义字符 描述
1 \ 将下一字符标记为特殊字符、文本、向引用或反八进制转义符。例如,”n“匹配字符”n“,而”\n“匹配换行符。序列”\\\\“匹配”\\“,”\\(“匹配”(“。
2 \b 匹配一个字边界,所谓字符边界是指所在位置的一侧为单词字符,另一侧为非单词字符、字符串的开始或结束位置,也就是相当于`(?<!\w)(?=\w)
3 \B 非字边界匹配。”er\B“匹配”verb“中的”er“,但不匹配”never“中的”er“。
10 \t 制表符匹配。与 \x09 和 \cI 等效。
11 \v 垂直制表符匹配。与 \x0b 和 \cK 等效。
12 \r 匹配一个回车符。等效于 \x0d 和 \cM。
13 \n 换行符匹配。等效于 \x0a 和 \cJ。
14 \f 换页符匹配。等效于 \x0c 和 \cL。
15 \cx 匹配 x 指示的控制字符。例如,\cM 匹配 Control-M 或回车符。x 的值必须在 A-Za-z 之间。如果不是这样,则假定 c 就是”c“字符本身。

\b应用场景

基础应用
“\b”一般应用在需要匹配某一单词字符组成的子串,但这一字符不能包含在同样由单词字符组成的更长的子串中。
比如要替换掉一段英文中的单词“to”,而“today”显然不在替换的范围内,所以正则可以用“\bto\b”来限定。
**特殊情况 **
“\b”用在正则中,通常情况下都是表示单词边界的,只有在字符组中,它表示的是退格键,即
[a-z\b]
此处的“\b”表示的是退格键,而不是单词边界。

进制相关

序号 带进制的转义符 描述
1 \xn 匹配 n,此处的 n 是一个十六进制转义码。十六进制转义码必须正好是两位数长。例如,”\x41“匹配”A“。”\x041“与”\x04&1“等效。允许在正则表达式中使用 ASCII 代码。
2 \n 标识一个八进制转义码或反向引用。如果 \n 前面至少有 n 个捕获子表达式,那么 n 是反向引用。否则,如果 n 是八进制数 (0-7),那么 n 是八进制转义码。
3 \un 匹配 n,其中 n 是以四位十六进制数表示的 Unicode 字符。例如,\u00A9 匹配版权符号 (©)。

零宽断言 环视 前瞻后顾

正则表达式中有前瞻(Lookahead)和后顾(Lookbehind)的概念,这两个术语非常形象的描述了正则引擎的匹配行为。需要注意一点,正则表达式中的前和后和我们一般理解的前后有点不同。一段文本,我们一般习惯把文本开头的方向称作“前面”,文本末尾方向称为“后面”。但是对于正则表达式引擎来说,因为它是从文本头部向尾部开始解析的(可以通过正则选项控制解析方向),因此对于文本尾部方向,称为“前”,因为这个时候,正则引擎还没走到那块,而对文本头部方向,则称为“后”因为正则引擎已经走过了那一块地方

所谓的前瞻就是在正则表达式匹配到某个字符的时候,往“尚未解析过的文本”预先看一下,看是不是符合/不符合匹配模式,
后顾,就是在正则引擎已经匹配过的文本看看是不是符合/不符合匹配模式。符合和不符合特定匹配模式我们又称为肯定式匹配否定式匹配
现代高级正则表达式引擎一般都支持都支持前瞻,对于后顾支持并不是很广泛。
java 支持正向后瞻负向后瞻正向前瞻负向前瞻
而javascirpt只支持前瞻,不支持后顾。

表达式 名称 描述
(?=exp) 正向前瞻 匹配后面满足表达式exp的位置
(?!exp) 负向前瞻 匹配后面不满足表达式exp的位置
(?<=exp) 正向后瞻 匹配前面满足表达式exp的位置(JS不支持)
(?<!exp) 负向后瞻 匹配前面不满足表达式exp的位置(JS不支持)
口诀:
  • 有小于号的表示匹配前面,没有的表示匹配后面
  • 等号表示满足
  • 感叹号表示不满足

例如,’Windows (?=95|98|NT|2000)’ 能匹配 “Windows 2000” 中的 “Windows” ,但不能匹配 “Windows 3.1” 中的 “Windows”
而’Windows (?!95|98|NT|2000)’”Windows 3.1” 中的 “Windows”,但不能匹配匹配 “Windows 2000” 中的 “Windows”。

实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public static void main(String[] args)
{
String text="Java\n"
+ "Javascirpt\n"
+ "PostScirpt\n"
+ "TypeScirpt\n"
+ "HTML\n"
+ "CSS\n"
+ "C\n"
+ "C++\n"
+ "C#\n";
Pattern pattern=Pattern.compile("^(?![cC]).*",Pattern.MULTILINE);
Matcher matcher=pattern.matcher(text);
System.out.println("开头后面没有C的编程语言:");
while(matcher.find())
{
System.out.println(matcher.group());
}
pattern=Pattern.compile("^(.*)(?=Scirpt)(.*)",Pattern.MULTILINE+Pattern.CASE_INSENSITIVE);
matcher=pattern.matcher(text);
System.out.println("尾部带有Script的编程语言:");
while(matcher.find())
{
System.out.println(matcher.group(1)+" "+matcher.group(2));
}
}

运行效果:

1
2
3
4
5
6
7
8
9
10
开头后面没有C的编程语言:
Java
Javascirpt
PostScirpt
TypeScirpt
HTML
尾部带有Script的编程语言:
Java scirpt
Post Scirpt
Type Scirpt

参考链接https://www.cnblogs.com/dong-xu/p/6926064.html
参考链接https://blog.csdn.net/sprayabc/article/details/7868688

应用实例

在数字之间添加点号
最近我在用文字识别工具识别pdf文件上的标题,但是识别的不是很好,经常会把标题中的点号丢失掉。可以用正则表达式把没识别的点号加上。
匹配正则:(?<=\d)(\d),解释,匹配一个数字,这个数字前面有一个数字。
替换正则:.$1,解释:在匹配到的数字前面添加一个点号。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//测试数据:
// 3.1.2文档注释
// 31.2文档注释
// 312文档注释
// 3.12文档注释
String code = "312文档注释";
// 在数字中间添加点号
// 匹配一个数字,这个数字前有一个数字
Pattern insert = Pattern.compile("(?<=\\d)(\\d)");
Matcher matcher = insert.matcher(code);
StringBuffer sb = new StringBuffer();
while (matcher.find())
{
matcher.appendReplacement(sb, ".$1");
}
matcher.appendTail(sb);
System.out.println(sb.toString());

运行结果:

1
3.1.2文档注释

参考资料

https://www.jb51.net/article/19330.htm