java的String类提供了支持正则表达式的方法,并且java中Pattern提供了丰富的API支持各种正则表达式操作。
元字符是在java正则表达式中具有特殊含义的字符。
Java中正则表达式的元字符如下:
( ) [ ] { } \ ^ $ | ? * + . < > - = !
其中,[ ] 表示正则表达式中的字符类。
字符类 | 含义 |
---|---|
[abc] | 字符a、b、c |
[^abc] | 除了字符x、y、z以外的其他字符 |
[a-z] | 字符a和z之间的所有字符 |
a-cx-z | 字符a到c或x到z,其中包括字符a、b、c、x、y、z |
0-9&&[4-8] | 字符0到9和字符4到8的交集,即字符4、5、6、7、8 |
[a-z&&[^aeiou]] | 字符a到z中除了a、e、i、o、u以外的字符 |
除此之外,Java中还定义了一些预定义字符
预定义字符 | 含义 |
---|---|
. | 任何字符 |
\d | 数字字符 |
\D | 非数字字符 |
\s | 空格字符。 包括与[\ t \ n \ x0B \ f \ r]相同,即空格、标签、换行符、垂直标签、表单Feed、回车字符 |
\S | 非空格字符 |
\w | 一个字符,与[a-zA-Z0-9]相同 |
\W | 非字字符,与[^\w]相同 |
表示次数的符号
符号 | 次数 |
---|---|
* | 0次或者多次 |
+ | 1次或者多次 |
? | 0次或者1次 |
{n} | 恰好n次 |
{n,m} | 从n次到m次 |
java.util.regex提供了三个类,支持正则表达式:
正则表达式字符匹配流程:
首先,一个Pattern实例订制一个所用语法的正则表达式经过编译以后的表现模式。然后,一个Matcher实例利用Pattern实例的表现模式进行字符串匹配工作。
//将一个正则表达式编译并赋值给Pattern
public static Pattern compile(String regex) {
return new Pattern(regex, 0);
}
/**
*{@link #CASE_INSENSITIVE}, {@link #MULTILINE}, {@link #DOTALL},
* {@link #UNICODE_CASE}, {@link #CANON_EQ}, {@link #UNIX_LINES},
* {@link #LITERAL}, {@link #UNICODE_CHARACTER_CLASS}
* and {@link #COMMENTS}
*/
//将一个正则表达式编译并赋值给Pattern,并且增加指定flags,flags参数有以下几种。
public static Pattern compile(String regex, int flags) {
return new Pattern(regex, flags);
}
//得到flags值
public int flags() {
return flags;
}
//生成一个指定名字的Matcher对象
public Matcher matcher(CharSequence input) {
if (!compiled) {
synchronized(this) {
if (!compiled)
compile();
}
}
Matcher m = new Matcher(this, input);
return m;
}
//根据给定的正则表达式(pattern)编译后的表现模式对输入的字符串(input)进行匹配工作。
//需要注意这个方法只适用于匹配一次,不需要得到Matcher对象的情况
public static boolean matches(String regex, CharSequence input) {
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(input);
return m.matches();
}
//返回该对象所表达的正则表达式
public String pattern() {
return pattern;
}
//将目标字符串(input)按照给定的正则表达式(pattern)规则进行分割
public String[] split(CharSequence input) {
return split(input, 0);
}
//作用同上,但是要求字符串分割为指定个数(limit)
public String[] split(CharSequence input, int limit) {
int index = 0;
boolean matchLimited = limit > 0;
ArrayList<String> matchList = new ArrayList<>();
Matcher m = matcher(input);
// Add segments before each match found
while(m.find()) {
if (!matchLimited || matchList.size() < limit - 1) {
if (index == 0 && index == m.start() && m.start() == m.end()) {
// no empty leading substring included for zero-width match
// at the beginning of the input char sequence.
continue;
}
String match = input.subSequence(index, m.start()).toString();
matchList.add(match);
index = m.end();
} else if (matchList.size() == limit - 1) { // last one
String match = input.subSequence(index,
input.length()).toString();
matchList.add(match);
index = m.end();
}
}
// If no match was found, return this
if (index == 0)
return new String[] {input.toString()};
// Add remaining segment
if (!matchLimited || matchList.size() < limit)
matchList.add(input.subSequence(index, input.length()).toString());
// Construct result
int resultSize = matchList.size();
if (limit == 0)
while (resultSize > 0 && matchList.get(resultSize-1).equals(""))
resultSize--;
String[] result = new String[resultSize];
return matchList.subList(0, resultSize).toArray(result);
}
Pattern类中flag的类型:
Flag | 描述 |
---|---|
Pattern.CANON_BQ | 启用规范等效。 |
Pattern.CASE_INSENSITIVE | 启用不区分大小写的匹配。 |
Pattern.COMMENTS | 启用不区分大小写的匹配。 |
Pattern.DOTALL | 允许在模式中的空格和注释。忽略以#开头的空格和嵌入的注释,直到行的结尾。 |
Pattern.LITERAL | 启用模式的文字解析。 这个标志使元字符和转义序列作为正常字符。 |
Pattern.MULTILINE | 启用多行模式。 默认情况下,^和$匹配输入序列的开始和结束。 此标志使模式仅逐行匹配或输入序列的末尾。 |
Pattern.UNICODE_CASE | 启用支持Unicode的大小写。 与CASE_INSENSITIVE标志一起,可以根据Unicode标准执行不区分大小写的匹配。 |
Pattern.UNICODE_ CHARACTER_CLASS | 启用预定义字符类和POSIX字符类的Unicode版本。 设置此标志时,预定义字符类和POSIX字符类符合Unicode技术标准。 |
Pattern.UNIX_LINES | 启用Unix行模式。 设置此标志时,只有\ n字符被识别为行终止符。 |
//将最后一次匹配工作剩余的字符串添加到StringBuffer对象里
public StringBuffer appendTail(StringBuffer sb) {
sb.append(text, lastAppendPosition, getTextLength());
return sb;
}
//重设该Matcher对象
public Matcher reset() {
first = -1;
last = 0;
oldLast = -1;
for (int i = 0; i < groups.length; i++)
groups[i] = -1;
for (int i = 0; i < locals.length; i++)
locals[i] = -1;
for (int i = 0; i < localsPos.length; i++) {
if (localsPos[i] != null)
localsPos[i].clear();
}
lastAppendPosition = 0;
from = 0;
to = getTextLength();
modCount++;
return this;
}
//根据新制定的目标字符串重设Matcher对象
public Matcher reset(CharSequence input) {
text = input;
return reset();
}
//返回当前查找所获得的字符串的开始字符在原目标字符串中的位置
public int start() {
if (first < 0)
throw new IllegalStateException("No match available");
return first;
}
//返回当前查找所获得的和指定组匹配的子串的开始字符在原目标字符串中的位置
public int start(int group) {
if (first < 0)
throw new IllegalStateException("No match available");
if (group < 0 || group > groupCount())
throw new IndexOutOfBoundsException("No group " + group);
return groups[group * 2];
}
//返回当前查找所获得的字符串的最后一个字符在原目标字符串中的位置
public int end() {
checkMatch();
return last;
}
//返回当前查找所获得的和指定组匹配的子串的最后一个字符在原目标字符串中的位置
public int end(int group) {
checkMatch();
if (group < 0 || group > groupCount)
throw new IndexOutOfBoundsException("No group " + group);
return groups[group * 2 + 1];
}
//尝试在目标字符串中查找下一个匹配子串
public boolean find() {
int nextSearchIndex = last;
if (nextSearchIndex == first)
nextSearchIndex++;
// If next search starts before region, start it at region
if (nextSearchIndex < from)
nextSearchIndex = from;
// If next search starts beyond region then it fails
if (nextSearchIndex > to) {
for (int i = 0; i < groups.length; i++)
groups[i] = -1;
return false;
}
return search(nextSearchIndex);
}
//重设Matcher对象,尝试在目标字符串的指定位置查找下一个匹配子串
public boolean find(int start) {
int limit = getTextLength();
if ((start < 0) || (start > limit))
throw new IndexOutOfBoundsException("Illegal start index");
reset();
return search(start);
}
//返回当前查找所获得的匹配组的数量
public int groupCount() {
return groupCount;
}
//返回当前查找而获得的和指定组组匹配的所有子串内容
public String group() {
checkMatch();
return group(0);
}
//返回当前查找而获得的与指定的组匹配的子串内容
public String group(int group) {
checkMatch();
if (group < 0 || group > groupCount)
throw new IndexOutOfBoundsException("No group " + group);
if ((groups[group * 2] == -1) || (groups[group * 2 + 1] == -1))
return null;
return text.subSequence(groups[group * 2], groups[group * 2 + 1]).toString();
}
//检测目标字符串是否以匹配的子串起始
public boolean lookingAt() {
return match(from, NOANCHOR);
}
//尝试对整个目标字符展开匹配检测,也就是只有整个目标字符串完全匹配时才返回真值
public boolean matches() {
return match(from, ENDANCHOR);
}
//返回该Matcher对象的现有匹配模式,也就是对应的Pattern对象
public Pattern pattern() {
return parentPattern;
}
//将目标字符串里与既有模式相匹配的子串全部替换为指定的字符串
public String replaceAll(String replacement) {
reset();
boolean result = find();
if (result) {
StringBuilder sb = new StringBuilder();
do {
appendReplacement(sb, replacement);
result = find();
} while (result);
appendTail(sb);
return sb.toString();
}
return text.toString();
}
//将目标字符串里与既有模式相匹配的第一个子串替换为指定的字符串
public String replaceFirst(String replacement) {
if (replacement == null)
throw new NullPointerException("replacement");
reset();
if (!find())
return text.toString();
StringBuilder sb = new StringBuilder();
appendReplacement(sb, replacement);
appendTail(sb);
return sb.toString();
}
请实现一个函数用来匹配包括’.‘和’*‘的正则表达式。模式中的字符’.‘表示任意一个字符,而’*'表示它前面的字符可以出现任意次(包含0次)。 在本题中,匹配是指字符串的所有字符匹配整个模式。 例如,字符串"aaa"与模式"a.a"和"abaca"匹配,但是与"aa.a"和"ab*a"均不匹配
代码
public static void main(String[] args) {
System.out.println( match(new char[]{'a', 'a', 'a'}, new char[]{'a', '.', 'a'}));
}
public static boolean match(char[] str, char[] pattern) {
String regex = "", string = "";
for (int i = 0; i < pattern.length; i++) {
regex += pattern[i];
}
for (int i = 0; i < str.length; i++) {
string += str[i];
}
Pattern pattern1 =Pattern.compile(regex);
Matcher matcher=pattern1.matcher(string);
return matcher.matches();
}