1,概念
正则表达式(Regular Expression)起源于人类神经系统的研究。正则表达式的定义有以下几种:
① 用某种模式去匹配一类字符串的公式,它主要是用来描述字符串匹配的工具。
②述了一种字符串匹配的模式。可以用来检查字符串是否含有某种子串、将匹配的子串做替换或者从中取出符合某个条件的子串等。
③由普通字符(a-z)以及特殊字符(元字符)组成的文字模式,正则表达式作为一个模版,将某个字符模式与所搜索的字符串进行匹配。
④用于描述某些规则的的工具。这些规则经常用于处理字符串中的查找或替换字符串。也就是说正则表达式就是记录文本规则的代码。
⑤用一个字符串来描述一个特征,然后去验证另一个字符串是否符合这个特征。
2,规则
1)元字符(Metacharacter)
元字符(Metacharacter)是一类非常特殊的字符,它能够匹配一个位置或字符集合中的一个字符,如:、 \w等。根据功能,元字符可以分为两种类型:匹配位置的元字符和匹配字符的元字符。
1.1 ^(脱字符号)
匹配一个位置;匹配行的开头。单个^匹配任意行。
^string 匹配以string开头的行
1.2 $(美元符号)
匹配一个位置;匹配行的结尾。单个$匹配一个空行。
string$ 匹配以string结尾的行
^string$ 匹配以string开始和结尾的行
1.3 \b
匹配一个位置;匹配单词的开始和结尾,但\b不匹配空格、标点符号或换行符号。
\bstr 匹配以str开始的单词
str\b 匹配以str结尾的单词
2.1 .(点号)
匹配字符的元字符;匹配除换行之外的任意字符。
2.2 \w
匹配字符的元字符;\w匹配单词字符(包括字母、汉字、下划线和数字)。
2.3 \W
匹配字符的元字符;\W匹配任意非单词字符。
2.4 s\
匹配字符的元字符;\s匹配任意的空白字符,如空格、制表符、换行等。
2.5 \S
匹配字符的元字符;\S匹配任意的非空白字符。
2.6 \d
匹配字符的元字符;\d匹配任意数字字符。
2.7 \D
匹配字符的元字符;\D匹配任意的非数字字符。
^.$ 匹配一个非空行,在该行中可以包含除了换行符以外的任意字符。
^\w$ 匹配一个非空行,并且该行中只能包含字母、数字、下划线和汉字中的任意字符。
\ba\w\w\w\w\w\w\\b 匹配以字母a开头长度等于7的任意单词
\ba\w\w\w\d\d\d\D\b 匹配以字母a开头后面有3个字符三个数字和1个非数字字符长度等于8的单词
2)字符类
字符类可以在[](方括号)中定义。
[012345] 匹配数字0到5中的任意一个。
[0-5] 匹配数字0到5中的任意一个。
<H[123456]> 匹配HTML标签中的H1到H6。
[Jj]ack 匹配字符串Jack或jack。
[a-z] 匹配任何小写字母
[A-Z] 匹配任意大写字母。
[-a] 匹配-或者a。如果要在字符类中包含连字符,则必须包含在第一位
[^abc] 匹配除了abc以外的任意字符
[^-] 匹配除了连字符以外的任意字符
a[^b] 匹配a之后不是b的字符串。
---常用字符类---
\w 匹配单词字符(包括字母、数字、下划线和汉字)
\W 匹配任意的非单词字符(包括字母、数字、下划线和汉字)
\s 匹配任意的空白字符,如空格、制表符、换行符、中文全角空格等
\S 匹配任意的非空白字符
\d 匹配任意数字
\D 匹配任意的非数字字符
\B 匹配不是单词开头或结束的位置
[abc] 匹配字符集中的任何字符
[^abc] 匹配除了字符集中包含字符的任意字符
[0-9a-z_A-Z_] 匹配任何数字、字母、下划线。等同于\w
\p{name} 匹配{name}指定的命名字符类中的任何字符
\P{name} 匹配除了{name}指定的命名字符类中之外的任何字符
. 匹配除了换行符号之外的任意字符
[^0-9a-zA-Z_] 等同于\W
4)字符转义
\r, \n 代表回车和换行符
\t 制表符
\\ "\"
\^ 匹配 ^ 符号本身
\$ 匹配 $ 符号本身
\. 匹配小数点(.)本身
\\? 匹配问号
5)限定符
正则表达式的元字符一次只能匹配一个位置或一个字符,如果需要匹配零个一个或多个字符时,则需要使用限定符。
* 匹配前面的子表达式零次或多次。例如,zo* 能匹配 "z" 以及 "zoo"。 * 等价于{0,}。
+ 匹配前面的子表达式一次或多次。例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等价于 {1,}。
? 匹配前面的子表达式零次或一次。例如,"do(es)?" 可以匹配 "do" 或 "does" 中的"do" 。? 等价于 {0,1}。
{n} n是一个非负整数。匹配确定的 n 次。例如,'o{2}' 不能匹配 "Bob" 中的 'o',但是能匹配 "food" 中的两个 o。
{n,} n 是一个非负整数。至少匹配n 次。例如,'o{2,}' 不能匹配 "Bob" 中的 'o',但能匹配 "foooood" 中的所有 o。'o{1,}' 等价于 'o+'。'o{0,}' 则等价于 'o*'。
{n,m} m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。刘, "o{1,3}" 将匹配 "fooooood" 中的前三个 o。'o{0,1}' 等价于 'o?'。请注意在逗号和两个数之间不能有空格。
*? 尽可能少的使用重复的第一个匹配
+? 尽可能少的使用重复但至少使用一次
?? 如果有可能使用零次重复或一次重复。
{n}? 等同于{n}
{n,}? 尽可能少的使用重复但至少重复n次
{n,m}? 介于n次和m次之间,尽可能少的使用重复。
6)匹配方式
我们普通的字符类均是贪婪匹配,如果在字符类后加个问号(?)则表示懒惰匹配,要成为支配性匹配则在懒惰匹配后加个问号(?).
①惰性匹配
趋向于最小长度匹配。
先看字符串中的第一个字母是不是一个匹配,如果单独一个字符还不够就读入下一个字符,如果还没有发现匹配,就不断地从后续字符中读取,只道发现一个合适的匹配,然后开始下一次的匹配。
②贪婪匹配
趋向于最大长度匹配。
先看整个字符串是不是一个匹配,如果没有发现匹配,它去掉字符串中最后一个字符并再次尝试,如果还没有发现匹配,那么再次去掉最后一个字符,这个过程会一直重复直到发现一个匹配或字符串不剩一个字符为止。
③支配性匹配
只尝试匹配整个字符串,如果整个字符串不能产生一个匹配,则不再进行尝试。
7)断言(零宽断言,环视)
环视强调的是它所在的位置,前面或者后面,必须满足环视表达式中的匹配情况,才能匹配成功。
环视可以认为是虚拟加入到它所在位置的附加判断条件,并不消耗正则的匹配字符。
①类型
(一)肯定和否定
1、肯定:(?=exp) 和 (?<=exp)
2、否定:(?!exp) 和 (?
②举例
/a(?=\d) //匹配a1,a2 不匹配ab,a
3,字符串处理
1)匹配-matches方法
// 校验一串数字,要求第一位不能是0,长度为5-15位
private static void match(String str) {
String regex = "[1-9]\\d{4,14}";
boolean flag = str.matches(regex);
if (flag) {
System.out.println("...is ok");
} else {
System.out.println("...不合法");
}
}
2)切割-split()方法
private static void split_str(String str){
String reg = " +";//按照多个空格来进行切割
String[] arr = str.split(reg);
for(String s : arr){
System.out.println(s);
}
}
3)替换-replaceAll(regex,str)方法。
//替换:将重叠的字符替换成单个字母。zzzz->z
public static void replaceAll_str(String str){
/*
* //.匹配任意一个字符,不包括换行
* (.)小括号表示捕获这个匹配到的字符
* \\1表示捕获的组号,也就是()内的字符
* 那么(.)\\1+就是匹配重复出现的字符串一个或者多个
*/
String reg = "(.)\\1+";
String newStr = "$1";
str = str.replaceAll(reg,newStr);
System.out.println(str);
}
4)获取
void match_str(String msgRlt){
String strReg =
"JSONSTART-([\\s\\S]*)-JSONEND";
Pattern pattern = Pattern.compile(strReg);
Matcher match = pattern.matcher(msgRlt);
// 如果匹配到内容,list添加数据
while (match.find()) {
String s = match.group(1);
if (!s.contains("-JSONENDJSONSTART-")) {
listRlt.add(s);
}else{
match_str("JSONSTART-" + s.substring(0, s.indexOf("-JSONENDJSONSTART-")+18));
match_str(s.substring(s.indexOf("-JSONENDJSONSTART-"), s.length()) + "-JSONEND");
}
}
}
4,应用举例
1)检查字符串是否只包含数字的字符串
public final static boolean isNumeric(String s) {
if (s != null && !"".equals(s.trim()))
return s.matches("^[0-9]*$");
else
return false;
}
2)截取字符串中的数字字符串
public static String cutOutNum(String s){
String regEx = "[^0-9]";
Pattern p = Pattern.compile(regEx);
Matcher m = p.matcher(s);
s = m.replaceAll("");
return s;
}