https://blog.csdn.net/m0_62618110/article/details/123704869
Java 正则表达式
0 概述
简介
正则表达式(regex)是一个字符串,由字面值字符和特殊符号组成,是用来描述匹配一个字符串集合的模式,可以用来匹配、查找字符串。
正则表达式的两个主要作用:
- 查找:在字符串中查找符合固定模式的子串
- 匹配:整个字符串是否符合某个格式
在匹配和查找的基础上,实现替换、分割等操作。
基本实例
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
| import java.util.regex.Matcher; import java.util.regex.Pattern; public class RegexMatches { public static void main( String[] args ){ String line = "This order was placed for QT3000! OK?"; String pattern = "(\\D*)(\\d+)(.*)"; Pattern r = Pattern.compile(pattern); Matcher m = r.matcher(line); if (m.find( )) { System.out.println("Found value: " + m.group(0) ); System.out.println("Found value: " + m.group(1) ); System.out.println("Found value: " + m.group(2) ); System.out.println("Found value: " + m.group(3) ); } else { System.out.println("NO MATCH"); } } }
|
1 正则表达式语法
- 在其他语言中,
\\表示:我想要在正则表达式中插入一个普通的(字面上的)反斜杠,请不要给它任何特殊的意义。
- 在 Java 中,
\\ 表示:我要插入一个正则表达式的反斜线,所以其后的字符具有特殊的意义。
- 不要在重复词符中使用空白。如B{3,6} ,不能写成 B{3, 6}。空格也是有含义的。
- 可以使用括号来将模式分组。(ab){3}匹配ababab , 而ab{3} 匹配 abbb。
| 字符 |
匹配 |
示例 |
| . |
任意单个字符,除换行符外 |
jav.匹配java |
| [ ] |
[ ] 中的任意一个字符 |
java匹配j[abc]va |
| - |
[ ] 内表示字符范围 |
java匹配[a-z]av[a-g] |
| ^ |
在[ ]内的开头,匹配除[ ]内的字符之外的任意一个字符 |
java匹配j[^b-f]va |
|
|
或 |
| \ |
将下一字符标记为特殊字符、文本、反向引用或八进制转义符 |
(匹配( |
| $ |
匹配输入字符串结尾的位置。如果设置了 RegExp 对象的 Multiline 属性,$ 还会与”\n”或”\r”之前的位置匹配。 |
;$匹配位于一行及外围的;号 |
| * |
零次或多次匹配前面的字符 |
zo*匹配zoo或z |
| + |
一次或多次匹配前面的字符 |
zo+匹配zo或zoo |
| ? |
零次或一次匹配前面的字符 |
zo?匹配z或zo |
| p{n} |
n 是非负整数。正好匹配 n 次 |
o{2}匹配food中的两个o |
| p{n,} |
n 是非负整数。至少匹配 n 次 |
o{2}匹配foood中的所有o |
| p{n,m} |
M 和 n 是非负整数,其中 n<= m。匹配至少 n 次,至多 m 次 |
o{1,3}匹配fooood中的三个o |
| \p{P} |
一个标点字符 !”#$%&’()*+,-./:;<=>?@[]^_’{ |
}~ |
| \b |
匹配一个字边界 |
va\b匹配java中的va,但不匹配javar中的va |
| \B |
非字边界匹配 |
va\B匹配javar中的va,但不匹配java中的va |
| \d |
数字字符匹配 |
1[\d]匹配13 |
| \D |
非数字字符匹配 |
[\D]java匹配Jjava |
| \w |
单词字符 |
java匹配[\w]ava |
| \W |
非单词字符 |
$java匹配[\W]java |
| \s |
空白字符 |
Java 2匹配Java\s2 |
| \S |
非空白字符 |
java匹配 j[\S]va |
| \f |
匹配换页符 |
等效于\x0c和\cL |
| \n |
匹配换行符 |
等效于\x0a和\cJ |
分组说明
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 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| 正则表达式-字符类
- 语法示例:
1. \[abc\]:代表a或者b,或者c字符中的一个。 2. \[^abc\]:代表除a,b,c以外的任何字符。 3. [a-z]:代表a-z的所有小写字符中的一个。 4. [A-Z]:代表A-Z的所有大写字符中的一个。 5. [0-9]:代表0-9之间的某一个数字字符。 6. [a-zA-Z0-9]:代表a-z或者A-Z或者0-9之间的任意一个字符。 7. [a-dm-p]:a 到 d 或 m 到 p之间的任意一个字符。
正则表达式-逻辑运算符
- 语法示例: 1. &&:并且 2. | :或者
正则表达式-预定义字符
- 语法示例: 1. "." : 匹配任何字符。 2. "\d":任何数字[0-9]的简写; 3. "\D":任何非数字\[^0-9\]的简写; 4. "\s": 空白字符:[ \t\n\x0B\f\r] 的简写 5. "\S": 非空白字符:\[^\s\] 的简写 6. "\w":单词字符:[a-zA-Z_0-9]的简写 7. "\W":非单词字符:\[^\w\]
正则表达式-数量词
- 语法示例: 1. X? : 0次或1次 2. X* : 0次到多次 3. X+ : 1次或多次 4. X{n} : 恰好n次 5. X{n,} : 至少n次 6. X{n,m}: n到m次(n和m都是包含的)
正则表达式-分组括号()
|
2 基本概念
Patter类和Matcher类
Pattern 类:
pattern 对象是一个正则表达式的编译表示。Pattern 类没有公共构造方法。要创建一个 Pattern 对象,你必须首先调用其公共静态编译方法,它返回一个 Pattern 对象。该方法接受一个正则表达式作为它的第一个参数。
Matcher 类:
Matcher 对象是对输入字符串进行解释和匹配操作的引擎。与Pattern 类一样,Matcher 也没有公共构造方法。你需要调用 Pattern 对象的 matcher 方法来获得一个 Matcher 对象。
匹配模式
1、Pattern.MULTILINE模式的用法
正则表达式中出现了^或者$, 默认只会匹配第一行. 设置了Pattern.MULTILINE模式,会匹配所有行。例如,
1 2 3 4 5 6
| Pattern p1 = Pattern.compile("^.*b.*$"); //输出false,因为正则表达式中出现了^或$,默认只会匹配第一行,第二行的b匹配不到。 System.out.println(p1.matcher("a\nb").find()); Pattern p2 = Pattern.compile("^.*b.*$",Pattern.MULTILINE); //输出true,指定了Pattern.MULTILINE模式,就可以匹配多行了。 System.out.println(p2.matcher("a\nb").find());
|
2、Pattern.DOTALL模式的用法
默认情况下, 正则表达式中点(.)不会匹配换行符, 设置了Pattern.DOTALL模式, 才会匹配所有字符包括换行符。例如,
1 2 3 4 5 6
| Pattern p1 = Pattern.compile("a.*b"); //输出false,默认点(.)没有匹配换行符 System.out.println(p1.matcher("a\nb").find()); Pattern p2 = Pattern.compile("a.*b", Pattern.DOTALL); //输出true,指定Pattern.DOTALL模式,可以匹配换行符。 System.out.println(p2.matcher("a\nb").find());
|
3、同时指定Pattern.MULTILINE和Pattern.DOTALL模式
实际情况中要是比较复杂的情况,可能Pattern.MULTILINE模式和Pattern.DOTAL模式需要同时指定来匹配多行,下面看一下,
1 2 3 4 5 6 7 8 9 10 11 12 13
| Pattern p1 = Pattern.compile("^a.*b$"); //输出false System.out.println(p1.matcher("cc\na\nb").find()); Pattern p2 = Pattern.compile("^a.*b$", Pattern.DOTALL); //输出false,因为有^或&没有匹配到下一行 System.out.println(p2.matcher("cc\na\nb").find()); Pattern p3 = Pattern.compile("^a.*b$", Pattern.MULTILINE); //输出false,匹配到下一行,但.没有匹配换行符 System.out.println(p3.matcher("cc\na\nb").find()); //指定多个模式,中间用|隔开 Pattern p4 = Pattern.compile("^a.*b$", Pattern.DOTALL|Pattern.MULTILINE); //输出true System.out.println(p4.matcher("cc\na\nb").find());
|
捕获组
- 捕获组是把多个字符当成一个单独单元进行处理的方法,它通过对括号内的字符分组来创建。
1 2 3 4 5 6 7 8
| 捕获组通过从左到右计算其括号来编号。
例如:在表达式((A)(B(C))) 中,存在四个这样的组:
((A)(B(C))) (A) (B(C)) (C)
|
- 捕获组可以通过调用matcher对象的groupCount方法来查看表达式有多少个分组。(groupCount方法返回一个int值,来表示matcher对象当前有多少个捕获组)
- 还有一个特殊的组零(group(0)),它代表整个表达式。(该组不包括在groupCount的返回值中)
- 以 (?) 开头的组是纯的非捕获 组,它不捕获文本,也不针对组合计进行计数。
3 Matcher用法
索引方法
- public int start()
返回以前匹配的初始索引。
- public int start(int group)
返回在以前的匹配操作期间,由给定组所捕获的子序列的初始索引
- public int end()
返回最后匹配字符之后的偏移量。
- public int end(int group)
返回在以前的匹配操作期间,由给定组所捕获子序列的最后字符之后的偏移量。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| import java.util.regex.Matcher; import java.util.regex.Pattern; public class RegexMatches { private static final String REGEX = "\\bcat\\b"; private static final String INPUT = "cat cat cat cattie cat"; public static void main( String[] args ){ Pattern p = Pattern.compile(REGEX); Matcher m = p.matcher(INPUT); int count = 0; while(m.find()) { count++; System.out.println("Match number "+count); System.out.println("start(): "+m.start()); System.out.println("end(): "+m.end()); } } }
|
匹配和查找方法
- public boolean lookingAt()
尝试将从区域开头开始的输入序列与该模式匹配。开头匹配。
- public boolean find()
尝试查找与该模式匹配的输入序列的下一个子序列。
- public boolean find(int start)
重置此匹配器,然后尝试查找匹配该模式、从指定索引开始的输入序列的下一个子序列。
- public boolean matches()
尝试将整个区域与模式匹配。全局匹配。
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 27
| import java.util.regex.Matcher; import java.util.regex.Pattern; public class RegexMatches { private static final String REGEX = "foo"; private static final String INPUT = "fooooooooooooooooo"; private static final String INPUT2 = "ooooofoooooooooooo"; private static Pattern pattern; private static Matcher matcher; private static Matcher matcher2; public static void main( String[] args ){ pattern = Pattern.compile(REGEX); matcher = pattern.matcher(INPUT); matcher2 = pattern.matcher(INPUT2); System.out.println("Current REGEX is: "+REGEX); System.out.println("Current INPUT is: "+INPUT); System.out.println("Current INPUT2 is: "+INPUT2); System.out.println("lookingAt(): "+matcher.lookingAt()); System.out.println("matches(): "+matcher.matches()); System.out.println("lookingAt(): "+matcher2.lookingAt()); } }
|
替换方法
- public Matcher appendReplacement(StringBuffer sb, String replacement)
实现非终端添加和替换步骤。
- public StringBuffer appendTail(StringBuffer sb)
实现终端添加和替换步骤。
- public String replaceAll(String replacement)
替换模式与给定替换字符串相匹配的输入序列的每个子序列。
- public String replaceFirst(String replacement)
替换模式与给定替换字符串匹配的输入序列的第一个子序列。
- public static String quoteReplacement(String s)
返回指定字符串的字面替换字符串。这个方法返回一个字符串,就像传递给Matcher类的appendReplacement 方法一个字面字符串一样工作。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| import java.util.regex.Matcher; import java.util.regex.Pattern; public class RegexMatches { private static String REGEX = "dog"; private static String INPUT = "The dog says meow. " + "All dogs say meow."; private static String REPLACE = "cat"; public static void main(String[] args) { Pattern p = Pattern.compile(REGEX); Matcher m = p.matcher(INPUT); INPUT = m.replaceAll(REPLACE); System.out.println(INPUT); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| import java.util.regex.Matcher; import java.util.regex.Pattern; public class RegexMatches { private static String REGEX = "a*b"; private static String INPUT = "aabfooaabfooabfoobkkk"; private static String REPLACE = "-"; public static void main(String[] args) { Pattern p = Pattern.compile(REGEX); Matcher m = p.matcher(INPUT); StringBuffer sb = new StringBuffer(); while(m.find()){ m.appendReplacement(sb,REPLACE); } m.appendTail(sb); System.out.println(sb.toString()); } }
|
4 String自带的正则表达式功能
见String