正则表达式是一种匹配和处理字符串
的文本处理工具,Java主要通过java.util.regex
包中的Pattern
、Matcher
和PatternSyntaxException
三个类来实现正则表达式。
常用语法
字符 | 含义 |
x | 字符x |
\ | 将下一字符标记为特殊字符、文本、反向引用或八进制转义符等。 |
字符类 | 含义 |
[abc] | a、b 或 c |
[a-zA-Z] | 大小写a至z |
[^abc] | 非a、b、c |
预定义字符类 | 含义 |
. | 任何字符 |
\d | 数字:[0-9] |
\D | 非数字: [^0-9] |
\w | 单词字符:[a-zA-Z_0-9] |
\s | 空白字符:[ \t\n\x0B\f\r] |
边界匹配器 | 含义 |
\s | 空白字符:[ \t\n\x0B\f\r] |
^ | 行的开头 |
$ | 行的结尾 |
\b | 单词边界 |
\B | 非单词边界 |
量词 | 含义 |
X? | X,一次或一次也没有 |
X* | X,零次或多次 |
X+ | X,一次或多次 |
X{n} | X,恰好 n 次 |
Logical 运算符 | 含义 |
XY | X 后跟 Y |
X|Y | X 或 Y |
(X) | X,作为捕获组 |
可以在API的Pattern类
中找到所有语法
Pattern与Matcher
通过静态方法Pattern.compile()编译正则表达式实例化Pattern对象,然后将想要检索的字符串传入Pattern对象的matcher()方法,生成一个Matcher对象。
Matcher类的几个重要方法:
boolean find()
尝试查找与该模式匹配的输入序列的下一个子序列。
int start()
返回以前匹配的初始索引。
int end()
返回最后匹配字符之后的偏移量。
Matcher appendReplacement(StringBuffer sb, String replacement)
实现非终端添加和替换步骤。
StringBuffer appendTail(StringBuffer sb)
实现终端添加和替换步骤。
boolean matches()
尝试将整个区域与模式匹配。
boolean lookingAt()
尝试将从区域开头开始的输入序列与该模式匹配。
String replaceFirst(String replacement)
替换模式与给定替换字符串匹配的输入序列的第一个子序列。
String replaceAll(String replacement)
替换模式与给定替换字符串相匹配的输入序列的每个子序列。
Matcher reset()
Matcher reset(CharSequence input)
重置匹配器。
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Test {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
/* Test for satrt() and end() */
System.out.println("/* Test for satrt() and end() */");
String regex = "\\bcat\\b";
String input = "cat cattie cat";
Pattern p = Pattern.compile(regex); // 实例化Pattern
Matcher m = p.matcher(input); // 实例化 Matcher
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());
}
/* Test for appendReplacement() and appendTail() */
System.out
.println("/* Test for appendReplacement() and appendTail() */");
regex = "\\d";
input = "hello1world2haha";
m = Pattern.compile(regex).matcher(input);
StringBuffer sb = new StringBuffer();
while (m.find()) {
m.appendReplacement(sb, "-");
}
m.appendTail(sb); // 剩下的接上
System.out.println(sb.toString());
/* Test for matches() and lookingAt() */
System.out.println("/* Test for matches() and lookingAt() */");
regex = "hello";
input = "hellooo";
m = Pattern.compile(regex).matcher(input);
System.out.println("isLookingAt?: " + m.lookingAt());
System.out.println("isMatches?: " + m.matches());
/* Test for String replaceFirst() and ... and reset() */
System.out.println("/* Test for String replaceFirst() and ... and reset() */");
regex = "cat"; // 注意与第一个Test相比是少了/b边界符的
input = "cat cattie cat";
m = p.compile(regex).matcher(input); // 实例化 Matcher
System.out.println("replaceFirst(): " + m.replaceFirst("dog"));
m.reset("cat1 cat2 cat3");
System.out.println("replaceAll(): " + m.replaceAll("dog"));
}
}
/* Test for satrt() and end() */
Match number 1
start(): 0
end(): 3
Match number 2
start(): 11
end(): 14
/* Test for appendReplacement() and appendTail() */
hello-world-haha
/* Test for matches() and lookingAt() */
isLookingAt?: true
isMatches?: false
/* Test for String replaceFirst() and ... and reset() */
replaceFirst(): dog cattie cat
replaceAll(): dog1 dog2 dog3
Group
组是用括号划分的正则表达式,用以获取与组内的相关信息。事实上,前面提到的方法,有些是带有一个int group参数的重载,就是用于组的。
如果我们在上面的代码里调用groupCount(),都是会返回0的,因为上面的所有正则表达式都不涉及组。
几个相关的方法:
String group()
返回由以前匹配操作所匹配的输入子序列。
String group(int group)
返回在以前匹配操作期间由给定组捕获的输入子序列。
int groupCount()
返回此匹配器模式中的捕获组数。
// 接上
/* Test for group() and groupCount() */
System.out.println("/* Test for group() and groupCount() */");
p = Pattern.compile("(\\d+,)(\\d+)"); // 两个组
m = p.matcher("12,34-56,78");
System.out.println("group count is: " + m.groupCount());
while (m.find()) {
System.out.println("group(): " + m.group()); // 等价于group(0)
System.out.println("group(1): " + m.group(1));
System.out.println("group(2): " + m.group(2));
}
/* Test for group() and groupCount() */
group count is: 2
group(): 12,34
group(1): 12,
group(2): 34
group(): 56,78
group(1): 56,
group(2): 78
首先匹配\\d+,\\d
,代表group(0)
;
group(1)
代表\\d+,
;
group(2)
代表\\d+
split
split是实现字符串切割的方法,可以直接通过String对象调用,也可以通过Pattern对象调用。
相关方法:
String[] split(String regex)
根据匹配给定的正则表达式来拆分此字符串。
String[] split(String regex, int limit)
根据匹配给定的正则表达式来拆分此字符串。
/* Test for split() */
System.out.println("/* Test for split() */");
String string = "i-1am-23leelit-456haha";
String[] strings1 = string.split("-\\d+");
for (String str : strings1)
System.out.print(str + " "); // 不换行
System.out.println("");
// same result
p = Pattern.compile("-\\d+");
String[] strings2 = p.split(string);
for (String str : strings2)
System.out.print(str + " "); // 不换行
System.out.println("");
// limit
String[] strings3 = string.split("-\\d+", 2); // limit 2
for (String str : strings3)
System.out.println(str); // 换行
/* Test for split() */
i am leelit haha
i am leelit haha
i
am-23leelit-456haha
material
you can also refer to the API