最近在实际开发中遇到了2个坑,都和正则表达式有关。一个是public String[] split(String regex)
,入参居然是正则表达式!!!另一个坑与Pattern、Matcher类的操作有关。都是对java的正则表达式不够熟悉导致。特地整理一下正则相关的知识。
一个字符串其实就是一个简单的正则表达式,例如 “Hello World”就是一个正则表达式,它匹配 “Hello World” 字符串(匹配自身)。
正则表达式(字符串)中往往含有特殊意义的字符,这些特殊字符被称为元字符。比如,“\\dcat”中的\\d就是元字符,代表0-9中的任何一个。字符串“0cat”、“1cat”等都是和正则表达式“\dcat”匹配的字符串。
元字符 | 在正则表达式中的写法 | 意义 |
---|---|---|
. | . | 代表任何一个字符。 |
\d | \\d | 代表0至9的任何一个数字 |
\D | \\D | 代表任何一个非数字的字符 |
\s | \\s | 代表空格类字符,比如’\t’ 、’\n’ 、’\f’ 、’\r’等 |
\S | \\S | 代表非空格类字符 |
\w | \\w | 代表可用于标识符的字符(不包括美元符号?)(包含汉字):[a-zA-Z_0-9] |
\W | \\W | 代表不能用于标识符的字符 |
\p{Lower} | \\p{Lower} | 小写字母[a-z] |
\p{Upper} | \\p{Upper} | 大写字母[A-Z] |
\p{ASCII} | \\p{ASCII} | ASCII字符 |
\p{Alpha} | \\p{Alpha} | 字母 |
\p{Digit} | \\p{Digit} | 数字[0-9] |
\p{Alnum} | \\p{Alnum} | 字母或数字 |
\p{Punct} | \\p{Punct} | 标点符号!"'#$@!%^&*()?>=:;<+-_`{|}~ |
\p{Graph} | \\p{Graph} | 可视字符:\p{Alnum}\p{Punct} |
\p{Print} | \\p{Print} | 可打印字符 |
\p{Blank} | \\p{Blank} | 空格或制表符[\t] |
\p{Cntrl} | \\p{Cntrl} | 控制字符[\x00-\x1F\x7F] |
\p{Sc} | \\p{Sc} | 匹配任何货币符号,如$、¥等 |
在正则表达式中可以用方括号括起来若干个字符来表示一个元字符,该元字符代表方括号中的任何一个字符。例如regex = “[159]ABC”,那么“1ABC”、“5ABC”都是和正则表达式regex匹配的字符串。
例如:
正则表达式 | 含义 |
---|---|
[abc] | 代表a、b、c中的任何一个; |
[^abc] | 代表除了abc以外的任何字符; |
[a-d] | 代表a至d中的任何一个 |
[a-zA-Z] | 代表英文字符(包括大写和小写)中的任何一个; |
由于“.”代表任何一个字符,所以正则表达式中如果想使用普通意义的点字符,必须使用[.]或者\56或者\.表示普通意义的点字符。
有趣的是,中括号里允许嵌套中括号,可以进行并、交、差运算。
例如:
正则表达式 | 含义 | 运算 |
---|---|---|
[a-d[m-p]] | 代表a至d,或者m至p中的任何一个字符。相当于[a-dm-p] | 并集 |
[a-z&&[def]] | 代表d、e、f中的任何一个字符 | 交集 |
[a-f&&[^bc]] | 代表a、d、e、f中的一个字符 | 差集 |
如果X代表正则表达式中的一个元字符或普通字符,那么限定符的作用可以下面表格的实例中得出:
限定符表
带限定修饰符的模式 | 意义 |
---|---|
X? | X出现0次或者1次 |
X* | X出现0次或者多次 |
X+ | X出现1次或者1次 |
X{n} | X恰好出现n次 |
X{n,} | X至少出现n次 |
X{n,m} | X出现n次至m次 |
XY | X的后缀是Y |
X|Y | X或Y |
方式一:"[a-zA-Z_0-9]+@[a-zA-Z_0-9]{2,6}(\\.[a-zA-Z_0-9]{2,3})+"
方式二:"\\w+@\\w{2,6}(\\.\\w{2,3})+"
2.匹配任意字符
方式一:[\\d\\D]*
方式二:[\\s\\S]*
方式三:[\\w\\W]*
3.匹配URL
方式一:"(http://|www)\56?\\w+\56{1}\\w+\56{1}\\p{Alpha}+"
这种匹配非常复杂。因为URL种类太多类,没有一个通用的正则表达式。
可以参见:正则表达式匹配URL或者网址
1、字符串判断功能
字符串对象可以调用public boolean matches(String regex)
方法可以判断当前字符串对象是否和参数regex指定的正则表达式匹配。
String regex = "[a-zA-Z]+";
if(str.matches(regex)){
System.out.println(str+"中的字符都是英文字符");
}
2、字符串拆分功能
字符串对象可以调用public String[] split(String regex)
根据给定的表达式匹配拆分此字符串。
String writeList = "gong,1|test,2|";
String[] result = writeList.split("\\|");
//被拆分成:“gong,1”和"test,2"
3、字符串替换功能
字符串对象可以调用public String replaceAll(String regex, String replacement)
方法返回一个字符串,该字符串是将当前字符串和参数regex指定的正则表达式匹配的子字符串用参数replacement指定的字符串替换后的字符串。(注意点:
replaceAll()方法返回一个新字符串,不会改变当前字符串。)
//例子一
String result = "12hello567world".replaceAll("[a-zA-Z]+", "你好");
//result结果为:“12你好567你好”
//例子二
String money = “89,234,678¥”;
String s = money.replaceAll("[,\\p{Sc}]","");
long number = Long.parseLong(s);
这两个类是java.util.regex包下专门用于进行模式匹配的类。使用他们检索字符串的步骤如下:
使用正则表达式regex做为参数得到一个称为模式的Pattern类的实例pattern。
例如:
String regex = "[abc]+";
Pattern pattern = Pattern.compile(regex);
模式对象是对正则表达式的封装。如果参数regex指定的正则表达式有错误,compile方法将抛出异常PatternSyntaxException。
模式对象pattern调用public Matcher matcher(CharSquence input)
可以得到Matcher对象matcher,称为匹配对象。参数input用于给出matcher要检索的字符串。input可以是String类和StringBuffer类的实例。
String input = "新浪:www.sina.cn,央视:http://www.cctv.com";
Matcher matcher = pattern.matcher(input);
Matcher对象matcher可以使用下列方法寻找字符串input中是否有和模式regex匹配的子序列。
函数:public boolean find() ;
作用:寻找input中和regex匹配的下一子序列。如果成功返回true,失败返回false。首次调用find方法时,寻找input中第1个和regex匹配的子序列,如果返回true,matcher再次调用find()方法时,就会从上一次匹配模式成功的子序列后开始寻找下一个匹配模式的子序列。另外,当find方法返回true时,matcher可以调用start()和end()方法可以得到该匹配模式子序列在input中的开始位置和结束位置。当find返回true时,matcher调用group()可以返回find方法本次找到的匹配模式的字符串。
函数:public boolean matches();
作用:判断input是否完全和regex匹配。
函数:public boolean lookingAt();
作用:matcher调用该方法判断从input的开始位置是否有和regex匹配的子序列。若lookingAt()方法返回true,matcher调用start()方法和end()方法可以得到lookingAt()方法找到的匹配模式的子序列在input中的开始位置和结束位置。若lookingAt()方法返回true,matcher调用group()可以返回lookingAt()方法找到的匹配模式的子序列。
函数:public boolean find(int start);
作用:matcher调用该方法判断input从参数start指定的位置开始是否有和regex匹配的子序列,参数start取值为0时,该方法和lookingAt()的功能相同。
函数:public String replaceAll(String replacement);
作用:matcher调用该方法可以返回一个字符串,该字符串是通过把input中与模式regex匹配的子字符串全部替换为参数replacement指定的字符串后得到的(input自身没有发生变化。)
函数:public String replaceFirst(String replacement);
作用:matcher调用该方法可以返回一个字符串,该字符串是通过把input中第一个与模式regex匹配的子字符串替换为参数replacement指定的字符串而得到的(注意input本身没有发生变化。)
//从一个字符串中获取整数,如DD20181026984,返回20181026984
private static long getNumFromStr(String str) {
if (StringUtils.isBlank(str)) {
return 0;
}
String regEx = "[^0-9]";
Pattern pattern = Pattern.compile(regEx);
Matcher matcher = pattern.matcher(str);
String trim = matcher.replaceAll("").trim();
int length = trim.length();
int startIndex = 0;
if (length > NUM_LENGTH) {
startIndex = length - NUM_LENGTH;
}
return NumberUtils.toLong(trim.substring(startIndex, length), 0);
}