正则表达式定义了字符串的模式。 正则表达式可以用来搜索、编辑或处理文本。 正则表达式并不仅限于某一种语言,但是在每种语言中有细微的差别。
一个字符串其实就是一个简单的正则表达式,例如 Hello World 正则表达式匹配 “Hello World” 字符串。 .(点号)也是一个正则表达式,它匹配任何一个字符如:“a” 或 “1”。
Java 正则表达式和 Perl 的是最为相似的。 java.util.regex 包主要包括以下三个类: Pattern 类: pattern 对象是一个正则表达式的编译表示。Pattern 类没有公共构造方法。要创建一个 Pattern对象,你必须首先调用其公共静态编译方法,它返回一个 Pattern 对象。该方法接受一个正则表达式作为它的第一个参数。 Matcher 类: Matcher 对象是对输入字符串进行解释和匹配操作的引擎。与Pattern 类一样,Matcher 也没有公共构造方法。你需要调用Pattern 对象的 matcher 方法来获得一个 Matcher 对象。 PatternSyntaxException: PatternSyntaxException 是一个非强制异常类,它表示一个正则表达式模式中的语法错误。
捕获组是把多个字符当一个单独单元进行处理的方法,它通过对括号内的字符分组来创建。 例如,正则表达式 (dog) 创建了单一分组,组里包含"d",“o”,和"g"。 捕获组是通过从左至右计算其开括号来编号。例如,在表达式((A)(B(C))),有四个这样的组: ((A)(B©)) (A) (B©) © 可以通过调用 matcher 对象的 groupCount 方法来查看表达式有多少个分组。groupCount 方法返回一个 int 值,表示matcher对象当前有多个捕获组。 还有一个特殊的组**(group(0))**,它总是代表整个表达式。该组不包括在 groupCount 的返回值中。
在其他语言中,\ 表示:我想要在正则表达式中插入一个普通的(字面上的)反斜杠,请不要给它任何特殊的意义。 在 Java 中,\ 表示:我要插入一个正则表达式的反斜线,所以其后的字符具有特殊的意义。 所以,在其他的语言中(如Perl),一个反斜杠 \ 就足以具有转义的作用,而在 Java 中正则表达式中则需要有两个反斜杠才能被解析为其他语言中的转义作用。**也可以简单的理解在 Java 的正则表达式中,两个 \ 代表其他语言中的一个 \,**这也就是为什么表示一位数字的正则表达式是 \d,而表示一个普通的反斜杠是 \\。
索引方法提供了有用的索引值,精确表明输入字符串中在哪能找到匹配:
public int start() 返回以前匹配的初始索引。 public int start(int group) 返回在以前的匹配操作期间,由给定组所捕获的子序列的初始索引 public int end() 返回最后匹配字符之后的偏移量。 public int end(int group) 返回在以前的匹配操作期间,由给定组所捕获子序列的最后字符之后的偏移量。
查找方法用来检查输入字符串并返回一个布尔值,表示是否找到该模式:
public boolean lookingAt() 尝试将从区域开头开始的输入序列与该模式匹配。 public boolean find() 尝试查找与该模式匹配的输入序列的下一个子序列。 public boolean find(int start) 重置此匹配器,然后尝试查找匹配该模式、从指定索引开始的输入序列的下一个子序列。 public boolean matches() 尝试将整个区域与模式匹配。
替换方法是替换输入字符串里文本的方法:
public Matcher appendReplacement(StringBuffer sb, String replacement) 实现非终端添加和替换步骤。 public StringBuffer appendTail(StringBuffer sb) 实现终端添加和替换步骤。 public String replaceAll(String replacement) 替换模式与给定替换字符串相匹配的输入序列的每个子序列。 public String replaceFirst(String replacement) 替换模式与给定替换字符串匹配的输入序列的第一个子序列。 public static String quoteReplacement(String s) 返回指定字符串的字面替换字符串。这个方法返回一个字符串,就像传递给Matcher类的appendReplacement 方法一个字面字符串一样工作。
Start 方法返回在以前的匹配操作期间,由给定组所捕获的子序列的初始索引,end 方法最后一个匹配字符的索引加 1。
matches 和 lookingAt 方法都用来尝试匹配一个输入序列模式。它们的不同是 matches 要求整个序列都匹配,而lookingAt 不要求。 lookingAt 方法虽然不需要整句都匹配,但是需要从第一个字符开始匹配。 这两个方法经常在输入字符串的开始使用。
replaceFirst 和 replaceAll 方法用来替换匹配正则表达式的文本。不同的是,replaceFirst 替换首次匹配,replaceAll 替换所有匹配。
Matcher 类也提供了appendReplacement 和 appendTail 方法用于文本替换
PatternSyntaxException 是一个非强制异常类,它指示一个正则表达式模式中的语法错误。 PatternSyntaxException 类提供了下面的方法来帮助我们查看发生了什么错误。
public String getDescription() 获取错误的描述。 public int getIndex() 获取错误的索引。 public String getPattern() 获取错误的正则表达式模式。 public String getMessage() 返回多行字符串,包含语法错误及其索引的描述、错误的正则表达式模式和模式中错误索引的可视化指示。
常用正则表达式: "[ ]":多个字符里找一个一个找 "^":在[ ]中代表取反,其次代表字符串开头 "$":代表字符串结尾 "\d":0-9 "\D":除0-9以外的 "\w":a-z0-9A-Z 字母数字下划线 "\s":将空白字符换掉 例如:空格,\n,\t ".":除换行\n外的所有字符 "\b":单词边界 "{n}":量词n次判断 "{m,n}":量词最少m次最多n次判断 "{n,}":量词最少n次,最多不限制 "*":匹配前面的表达式0次或多次 "+":匹配前面的表达式1次或 "?":匹配前面的表达式0次或1次 "()":分组
实例代码:
public static void test1() { // 最简单的元字符 String s = "a1b2a1d4";// 需要分析的字符串 String regex = "a1";// 正则 最简单的元字符 Pattern p = Pattern.compile(regex);// 编译 Matcher m = p.matcher(s);// 分析和匹配字符串s是否能匹配上 System.out.println(m);//java.util.regex.Matcher[pattern=a1 region=0,8 lastmatch=] String ok = m.replaceAll("_");// 替换找到的位置 System.out.println(ok); System.out.println(s); } public static void test2() { String s = "a1b2c1a1d4"; // String regex = "[abc]";//多个字符里找一个 _1_2_1_1d4 // String regex = "[a-e]";//a-e的字符全部被替换掉 _1_2_1_1_4 // String regex = "[d-hA-D]";//也可以写连续的几个范围,替换效果相同 a1b2c1a1_4 String regex = "[^a-c]";// 除了a-c的字符全换掉 a_b_c_a___ Pattern p = Pattern.compile(regex);// 编译 Matcher m = p.matcher(s);// 分析和匹配字符串s是否能匹配上 String ok = m.replaceAll("_");// 替换找到的位置 System.out.println(ok); } public static void test3() { String s = "*&^%$abcdefghigk123456789ABCDEFGH+-$%#"; String regex = "\\d";//在java中不能识别带\d,所以要写成\\d 代表0-9 *&^%$abcdefghigk=========ABCDEFGH+-$%# // String regex = "\\D";//除数字0-9数字之外的其他字符 ================123456789============= // String regex = "\\w";//代表a-z0-9A-Z *&^%$============================+-$%# Pattern p = Pattern.compile(regex);// 编译 Matcher m = p.matcher(s);// 分析和匹配字符串s是否能匹配上 String ok = m.replaceAll("=");// 替换找到的位置 System.out.println(ok); } public static void test4() { String s = "*&^%$abcdef ghigk1234567\n89ABCDEFGH+-\t$%#"; String regex = "\\s";//将空白字符换掉 例如:空格,\n,\t *&^%$abcdef<br>ghigk1234567<br>89ABCDEFGH+-<br>$%# // String regex = ".";//除换行\n外的所有字符 Pattern p = Pattern.compile(regex);// 编译 Matcher m = p.matcher(s);// 分析和匹配字符串s是否能匹配上 String ok = m.replaceAll("<br>");// 替换找到的位置 System.out.println(ok); } public static void test5() { String s = "this is a test isEmpty"; String regex = "is";//元字符 将所有的is都换了 th_ _ a test _Empty //如果不替代单词中的is 应设置单词边界 // String regex = "\\bis\\b";//左右两边加上 单词边界\b this _ a test isEmpty Pattern p = Pattern.compile(regex);// 编译 Matcher m = p.matcher(s);// 分析和匹配字符串s是否能匹配上 String ok = m.replaceAll("_");// 替换找到的位置 System.out.println(ok); } public static void test6() { String s = "abc is a abc abc"; String regex = "abc";//替换所有的abc _ is a _ _ // String regex = "^abc";//替换开头的abc _ is a abc abc // String regex = "abc$";//替换结尾的abc abc is a abc _ Pattern p = Pattern.compile(regex);// 编译 Matcher m = p.matcher(s);// 分析和匹配字符串s是否能匹配上 String ok = m.replaceAll("_");// 替换找到的位置 System.out.println(ok); } //量词{n}n次判断, //{m,n}最少m次最多n次判断, //{n,}最少n次,最多不限制 public static void test7() { String s = "456789"; //String regex = "\\d{6}";//判断六次是否字符为数字 //String regex = "\\d{3,6}";//最少3次最多6次判断 String regex = "\\d{3,}";//最少3次判断,最多不限制 Pattern p = Pattern.compile(regex);// 编译 Matcher m = p.matcher(s);// 分析和匹配字符串s是否能匹配上 System.out.println(m.matches());//返回boolean类型 } //*匹配前面的表达式0次或多次 //+匹配前面的表达式1次或多次 //?匹配前面的表达式0次或1次 public static void test8() { String s = "gd god good goood goooood"; String regex = "go?d";//g与d之间不管有多少个o都匹配上 Pattern p = Pattern.compile(regex);// 编译 Matcher m = p.matcher(s);// 分析和匹配字符串s是否能匹配上 String ok = m.replaceAll("_"); System.out.println(ok); } public static void test9() { String s = "a1b1c1dd"; String regex = "([a-z]\\d){3}";//()代表分组 将a-z字母与0-9数字组成的分组替换 Pattern p = Pattern.compile(regex);// 编译 Matcher m = p.matcher(s);// 分析和匹配字符串s是否能匹配上 String ok = m.replaceAll("_"); System.out.println(ok); } // 分组之后分配位置 2019-11-28-->11/28/2019 public static void test10() { String s = "2019-11-28"; // 月$2/日$3/年$1 String regex = "(\\d{4})-(\\d{2})-(\\d{2})";// ()代表分组 将a-z字母与0-9数字组成的分组替换 Pattern p = Pattern.compile(regex);// 编译 Matcher m = p.matcher(s);// 分析和匹配字符串s是否能匹配上 String ok = m.replaceAll("$2/$3/$1"); System.out.println(ok); } // 汉字邮箱的验证 public static void test11() { String s = "1987562050@qq.com"; //true String regex ="^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$";//邮箱正则表达式 // String s = "你好中国"; // String regex = " [u4e00-u9fa5]";// ??? Pattern p = Pattern.compile(regex);// 编译 Matcher m = p.matcher(s);// 分析和匹配字符串s是否能匹配上 System.out.println(m.matches()); } // 获得网页中图片的链接 public static void test12() { String s = "<img src=\"//game.gtimg.cn/images/lol/act/img/champion/Olaf.png\" alt=\"狂战士 奥拉夫\">"; String regex = "<img src=\"(.*?)\" alt=\"(.*?)\">"; Pattern p = Pattern.compile(regex);// 编译 Matcher m = p.matcher(s);// 分析和匹配字符串s是否能匹配上 while (m.find()) { System.out.println(m.group(1));// 正则中的第一个分组 game.gtimg.cn/images/lol/act/img/champion/Olaf.png System.out.println(m.group(2));// 正则中的第二个分组 //狂战士 奥拉夫 } }