正则表达式是一种匹配和处理字符串
的文本处理工具,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