一种强大灵活的文本处理工具
正则表达式是完全通用的,一次学会,处处可用。如Unix工具中的sed
和awk
,还有Python
和Perl
等编程语言,都可以用正则表达式。
1.1 基础
其他语言中,\\
代表插入一个普通的(字面上的)反斜杠,没有任何特殊含义。在Java中,\\
代表插入一个正则表达式的反斜杠,它后面的字符会有特殊意义。
打个比方,在正则表达式中,\d
表示一位数字。在Python里直接使用\d
表示一位数字,但在Java中,需要使用\\d
。
如果你想插入一个普通的反斜杠,在Java中应该是\\\\
。
常用的正则表达式语法
+
1次或者多次匹配前面的字符或者子表达式。如,hi+
匹配hi
和hii
()
捕获组。可以在表达式中用\i
引用第i个捕获组?
0次或1次匹配前面的字符或者子表达式。如,he(llo)?
匹配he
和hello
|
或操作。X|Y
表示X或Y
String类自带正则表达式工具
matches()
检查字符串是否与正则表达式匹配
public class IntegerMatch {
public static void main(String[] args) {
System.out.println("-1234".matches("-?\\d+")); // true
System.out.println("5678".matches("-?\\d+")); // true
System.out.println("+110".matches("-?\\d+")); // false 只能匹配-110和110
System.out.println("+110".matches("(-|\\+)\\d+")); // true +有特殊含义,需要转义
}
}
split()
将字符串从正则表达式匹配的地方切开
public class Splitting {
public static void main(String[] args) {
System.out.println(Arrays.toString("hello world".split(" ")));
System.out.println(Arrays.toString("hello;world".split(";")));
System.out.println(Arrays.toString("hello123world".split("\\d+")));
}
}
// 输出
[hello, world]
[hello, world]
[hello, world]
replaceFirst()
和replaceAll()
将正则表达式匹配部分替换掉
public class Replacing {
public static void main(String[] args) {
System.out.println("hello java, hello world".replaceFirst("hello", "ok"));
System.out.println("hello java, hello world".replaceAll("hello", "ok"));
}
}
1.2 正则表达式语法
列出一些常用语法,可在java.util.regex.Pattern
中查阅更多
字符 | 说明 |
---|---|
x | 指定字符x |
\\ | 反斜杠 |
\xhh | 十六进制值为0xhh的字符 |
\xhhhh | 十六进制值表示为0xhhhh的Unicode字符 |
\t | 制表符Tab |
\n | 换行符 |
\r | 回车 |
\f | 换页 |
\e | 转义 |
- 【例】匹配16进制字符
Integer.toHexString('A'); // "41"
"A".matches("\\x41"); // true
- 【例】匹配Unicode字符
// 中文的Unicode范围:\u4e00-\u9fa5
"你好".matches("[\\u4e00-\\u9fa5]+"); // true
字符类 | 说明 |
---|---|
[abc] | 包含a、b和c的任何字符(与a|b|c 作用相同) |
[^abc] | 除了a、b、c之外的字符(否定) |
[a-zA-Z] | 从a到z或从A到Z的任何字符(范围) |
[abc[def]] | 任意a、b、c、d、e、f字符(合并) |
[a-z&&[def]] | 任意d、e、f字符(交集) |
\s | 空白符(空格、tab、换行、换页、回车) |
\S | 非空白符([^\s]) |
\d | 数字[0-9] |
\D | 非数字[0-9] |
\w | 词字符[0-9a-zA-Z] |
\W | 非词字符[^\w] |
边界匹配符 | 说明 |
---|---|
^ | 一行的起始 |
$ | 一行的结束 |
\b | 词的边界 |
\B | 非词的边界 |
\G | 前一个匹配的结束 |
1.3 Pattern和Matcher
典型用法
Pattern p = Pattern.compile("a*b");
Matcher m = p.matcher("aaab");
boolean b = m.matches(); // true
String group = m.group(); // group = "aaab"
// static boolean matches(String regex, CharSequence input)
// 检查regex是否匹配整个CharSequence类型的input参数
boolean b0 = Pattern.matches("a*b", "aaab"); // true
Matcher.find() 方法可查找多个匹配
public class Finding {
public static void main(String[] args) {
Pattern p = Pattern.compile("\\w+");
Matcher m = p.matcher("hello mother fuxxer");
while (m.find()) {
System.out.println(m.group());
}
}
}
// hello
// mother
// fuxxer
组(Groups)
组是用括号划分的正则表达式,根据组的编号来引用某个组,组号为0代表整个表达式,组号1代表被第一对括号括起的组。
A(B(C))D
组0是ABCD
,组1是BC
,组2是C
。
public class Groups {
public static void main(String[] args) {
Pattern p = Pattern.compile("(\\d+)(\\w+)");
Matcher m = p.matcher("hello world1234java");
while (m.find()) {
for (int i = 0; i <= m.groupCount(); i++) {
System.out.println(m.group(i));
}
}
}
}
// 1234java
// 1234
// java
// 查看是否有重复字符
"java".matches(".*(\\S).*(\\1).*"); // true
"python".matches(".*(\\S).*(\\1).*"); // false
Pattern标记模式
Pattern Pattern.complie(String regex, int flag)
编译标记 | 效果 |
---|---|
Pattern.CASE_INSENSITIVE(?i) | 忽略大小写 |
Pattern.DOTALL(?s) | "."匹配所有字符,包括行终结符(默认不匹配行终结符) |
Pattern.MULTILINE(?m) | 告知正则表达式注意输入序列的换行符(^ 和$ 会匹配每一行的起始与结尾) |
“或”操作符组合多个标记
Pattern.complie("^java", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
1.4 split()
public class SplitDemo {
public static void main(String[] args) {
String input = "This!!unusual use!!of exclamation!!points";
System.out.println(Arrays.toString(Pattern.compile("!!").split(input)));
System.out.println(Arrays.toString(Pattern.compile("!!").split(input, 3)));
}
}
// [This, unusual use, of exclamation, points]
// [This, unusual use, of exclamation!!points]
1.5 替换操作
replaceFirst
与replaceAll
方法与上文类似,不再赘述。
appendReplacement
和appendTail
方法
public class AppendDemo {
public static void main(String[] args) {
Pattern p = Pattern.compile("python");
Matcher m = p.matcher("hello python, I love python!");
StringBuffer sb = new StringBuffer();
while (m.find()) {
m.appendReplacement(sb, "java");
}
m.appendTail(sb);
System.out.println(sb);
}
}
// hello java, I love java!