Java 正则表达式
正则表达式,听起来有点陌生,但是干我们这行的应该经常会用到,最常用的莫过于在搜索了,我们经常会用Windows资源管理器中搜索某个同意后缀名的文件,例如我们要找当前文件夹下的所有java文件,那么就可以在资源管理器的搜索框中输入“*.java”,又或者我们要搜索文件名以“Java”这个字符串开头的文件,我们就可以输入“Java?”,这两个例子中的”*”(星号)和”?”(问号)分别代表了“任意长度的任意字符”和”一个字符长度的任意字符”,但是正则表达式远不止这两个,接下来就来学习一些比较常用的正则表达式知识吧:
1. 正则表达式的作用
正则表达式是专门用于操作字符串,我们常用的搜索和替换操作就是要求我们提供与预期的搜索结果匹配的确切字符串,虽然Java当中对字符串执行简单搜索和替换任务可能已经足够了,但这样缺乏灵活性,若采用正则表达式来做这些工作,效率和灵活性都会比较高了。正则表达式的用途有:
1) 匹配字符串:
例如,可以测试输入字符串,以查看字符串内是否出现电话号码模式或信用卡号码模式。这称为数据验证。
2) 替换字符串:
可以使用正则表达式来识别文档中的特定文本,完全删除该文本或者用其他文本替换它。
3) 切割字符串:
将文本按照一定的模式来分割成若干子串。
4) 获取字符串:
取出字符串中符合某个模式的子串。
优点:正则表达式可以简化对字符串的复杂操作。
缺点:如果正则表达式写的很复杂,可阅读性就会非常差。
2. 正则表达式的基本语法
由于正则表达式的语法比较多,这里只列举部分,详细的正则表达式语法请点击这里。
部分语法表格如下:
1) 字符匹配语法:
字符语法 | 语法解释 | 语法例子 |
\d | 匹配数字(0~9) | ‘\d’匹配8,不匹配12; |
\D | 匹配非数字 | ‘\D’匹配c,不匹配3; |
\w | 匹配任意单字符 | ‘\w\w’ 匹配A3,不匹配@3; |
\W | 匹配非单字符 | ‘\W’匹配@,不匹配c; |
\s | 匹配空白字符 | ‘\d\s\d’匹配3 d,不匹配abc; |
\S | 匹配非空字符 | ‘\S\S\S’匹配A#4,不匹配3 d; |
. | 匹配任意字符 | ‘....’匹配A$ 5,不匹配换行; |
[…] | 匹配括号中任意字符 | [b-d]匹配b、c、d, 不匹配e; |
[^…] | 匹配非括号字符 | [^b-z]匹配a,不匹配b-z的字符; |
2) 重复匹配语法:
重复语法 | 语法解释 | 语法例子 |
{n} | 匹配n次字符 | \d{3}匹配\d\d\d,不匹配\d\d或\d\d\d\d |
{n,} | 匹配n次和n次以上 | \w{2}匹配\w\w和\w\w\w以上,不匹配\w |
{n,m} | 匹配n次上m次下 | \s{1,3}匹配\s,\s\s,\s\s\s,不匹配\s\s\s\s |
? | 匹配0或1次 | 5?匹配5或0,不匹配非5和0 |
+ | 匹配一次或多次 | \S+匹配一个以上\S,不匹配非一个以上\S |
* | 匹配0次以上 | \W*匹配0以上\W,不匹配非N*\W |
3) 字符定位语法:
重复语法 | 语法解释 | 语法例子 |
^ | 定位后面模式开始位置 | |
$ | 前面模式位于字符串末端 | |
\A | 前面模式开始位置 | |
\z | 前面模式结束位置 | |
\Z | 前面模式结束位置(换行前) | |
\b | 匹配一个单词边界 | |
\B | 匹配一个非单词边界 |
4) 转移匹配语法:
转义语法 | 涉及字符(语法解释) | 语法例子 |
“\”+实际字符 | \ . * + ? | ( ) { }^ $ | 例如:\\匹配字符“\” |
\n | 匹配换行 | |
\r | 匹配回车 | |
\t | 匹配水平制表符 | |
\v | 匹配垂直制表符 | |
\f | 匹配换页 | |
\nnn | 匹配一个8进制ASCII | |
\xnn | 匹配一个16进制ASCII | |
\unnnn | 匹配4个16进制的Uniode |
下面我们结合例子来学习一下正则表达式的语法:
package learn.regex;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/** 正则表达式*/
public class RegexDemo {
/** 匹配 */
public static boolean matchsString(String string, String regex) {
if (string != null && regex != null) {
return string.matches(regex);
} else {
return false;
}
}
/** 替换 */
public static String replaceString(String string, String regex,String newString) {
if (string != null && regex != null) {
return string.replaceAll(regex, newString);
} else {
return null;
}
}
/** 分割 */
public static String[] splitString(String string, String regex) {
if (string != null && regex != null) {
return string.split(regex);
} else {
return null;
}
}
/** 换行打印 */
public static void println(String string) {
System.out.println(string);
}
/** 不换行打印 */
public static void print(String string) {
System.out.print(string);
}
/** 测试 */
public static void main(String[] args) {
/********************************************************************************************/
/*
* 1.反斜杠(\\)字符串分割测试*/
println("1.反斜杠(\\)字符串分割测试");
String splitString1 = "C:\\Windows\\notepad.exe";
/*因为在Java的字符串中一个反斜杠的意义是"转念字符", 所以要得到一个真正的反斜杠字符"\",
* 必须输入一个两个反斜杠(\\), 也就是要用第一个反斜杠转义第二个反斜杠,而我们这里写的反斜杠又是要用于正则表达式中,
* 正则表达式中的一个反斜杠的意义同Java字符串一样,所以这里要输入四个反斜杠
*/
String splitRegex1 = "\\\\";
String splitResult1[] = splitString(splitString1, splitRegex1);
println("\t被分割的的字符串:" + splitString1);
println("\t正则表达式:" + splitRegex1);
println("\t分割字符串的结果:");
for (int i = 0; i < splitResult1.length; i++) {
String s = splitResult1[i];
println("\t\t第" + (i + 1) + "个子串: " + s);
}
/********************************************************************************************/
/*
* 2.叠词字符串分割测试
*/
println("2.叠词字符串分割测试");
String splitString2 = "How arre yooou?iammmmm fine.";
/*
* 这个正则表达式使用了分组的概念,为了让规则的结果被重用,则可以用一对小括号”()“将里面的内容分为一个组,
* 并自动给这个组从左至右编号(从1开始),使用反斜杠加上组的编号(就是这里的”\1“)引用这个组,
* 这里的加号”+“代表前面的叠词出现了一次或多次
*/
String splitRegex2 = "(.)\\1+";
String splitResult2[] = splitString(splitString2, splitRegex2);
println("\t被分割的的字符串:" + splitString2);
println("\t正则表达式:" + splitRegex2);
println("\t分割字符串的结果:");
for (int i = 0; i < splitResult2.length; i++) {
String s = splitResult2[i];
println("\t\t第" + (i + 1) + "个子串: " + s);
}
/********************************************************************************************/
/*
* 3.替换重复字母测试
*/
println("3.替换重复字母测试");
String replaceString1 = "????****abcdefffghijjjjkkklmnopqrstttuvvvvwxyz你你你你你你你你好好好";
/*
* 这里我们将一串字母中的连续重复字母去重,replaceMent1中的美元符($)加上组的编号可以在替换时取到前面替换规则(replaceRegex1)中该编号对应组的值
*/
String replaceRegex1 = "(.)\\1+";
String replaceMent1="$1";
String replaceResult1 = replaceString(replaceString1, replaceRegex1,replaceMent1);
println("\t被替换前的字符串:" + replaceString1);
println("\t正则表达式:" + replaceRegex1);
println("\t被替换后的字符串:"+ replaceResult1);
/********************************************************************************************/
/*
* 4.电话号码匹配测试
*/
println("4.电话号码匹配测试");
String matchsString1 = "18888888888";
/*
* 匹配电话号码,第一位是1,第二位是(3、5、7、8)中的一位,后面还有9位任意数字
*/
String matchsRegex1 = "1[3|5|7|8]\\d{9}";
boolean matchsResult1 = matchsString(matchsString1,matchsRegex1);
println("\t匹配测试的字符串:" + matchsString1);
println("\t正则表达式:" + matchsRegex1);
println("\t匹配的结果:"+ matchsResult1);
/********************************************************************************************/
/*
* 5.子串获取测试
*/
println("5.子串获取测试");
String subString1 = "no.1abcno.2defno.3ghijk";
/*
* 这里我们能取出以”no.“开头,以数字结尾的子串,第一位是1,第二位是(3、5、7、8)中的一位,后面还有9位任意数字,使用Pattern类和Matcher类来获取子串
*/
String subRegex1 = "no\\.\\d+";
Pattern pattern=Pattern.compile(subRegex1);
Matcher matcher=pattern.matcher(subString1);
println("\t获取子串测试的字符串:" + subString1);
println("\t正则表达式:" + subRegex1);
println("\t符合规则的子串:");
for (int i=1;matcher.find();i++) {
String s = matcher.group();
println("\t\t第" + i + "个符合规则的子串: " + s+",在原字符中的位置是:"+matcher.start()+"-->"+matcher.end());
}
}
}
程序输出:
1.反斜杠(\)字符串分割测试
被分割的的字符串:C:\Windows\notepad.exe
正则表达式:\\
分割字符串的结果:
第1个子串: C:
第2个子串: Windows
第3个子串: notepad.exe
2.叠词字符串分割测试
被分割的的字符串:How arre yooou?iammmmm fine.
正则表达式:(.)\1+
分割字符串的结果:
第1个子串: How a
第2个子串: e y
第3个子串: u?i a
第4个子串: fine.
3.替换重复字母测试
被替换前的字符串:????****abcdefffghijjjjkkklmnopqrstttuvvvvwxyz你你你你你你你你好好好
正则表达式:(.)\1+
被替换后的字符串:?*abcdefghijklmnopqrstuvwxyz你好
4.电话号码匹配测试
匹配测试的字符串:18888888888
正则表达式:1[3|5|7|8]\d{9}
匹配的结果:true
5.子串获取测试
获取子串测试的字符串:no.1abcno.2defno.3ghijk
正则表达式:no\.\d+
符合规则的子串:
第1个符合规则的子串: no.1,在原字符中的位置是:0-->4
第2个符合规则的子串: no.2,在原字符中的位置是:7-->11
第3个符合规则的子串: no.3,在原字符中的位置是:14-->18
3. 常用的正则表达式
用途 | 表达式 |
验证手机号码 | 1[3|5|7|8|]\d{9} |
提取信息中的网络链接 | (h|H)(r|R)(e|E)(f|F) *=*('|")?(\w|\\|\/|\.)+('|"|*|>)? |
提取信息中的邮件地址 | \w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)* |
提取信息中的图片链接 | (s|S)(r|R)(c|C)*=*('|")?(\w|\\|\/|\.)+('|"|*|>)? |
提取信息中的IP地址 | (\d+)\.(\d+)\.(\d+)\.(\d+) |
提取信息中的中国手机号码 | (86)*0*13\d{9} |
提取信息中的中国固定电话号码 | (\(\d{3,4}\)|\d{3,4}-|\s)?\d{8} |
提取信息中的中国电话号码(包括移动和固定电话) | (\(\d{3,4}\)|\d{3,4}-|\s)?\d{7,14} |
提取信息中的中国邮政编码 | [1-9]{1}(\d+){5} |
提取信息中的中国身份证号码 | \d{18}|\d{15} |
提取信息中的整数 | \d{18}|\d{15} |
提取信息中的浮点数(即小数) | (-?\d*)\.?\d+ |
提取信息中的任何数字 | (-?\d*)(\.\d+)? |
提取信息中的中文字符串 | [\u4e00-\u9fa5]* |
提取信息中的双字节字符串 (汉字) | [^\x00-\xff]* |
不记得的时候多查查文档就好了