边界处理
^
在中括号内表示取反的意思[^]
, 如果不在中括号里则表示字符串的开头
public class Demo6 { private static void p(Object o){ System.out.println(o); } public static void main(String[] args) { /** * ^ The beginning of a line 一个字符串的开始 * $ The end of a line 字符串的结束 * \b A word boundary 一个单词的边界, 可以是空格, 换行符等 */ p("hello sir".matches("^h.*")); p("hello sir".matches(".*r$")); p("hello sir".matches("^h[a-z]{1,3}o\\b.*")); p("hellosir".matches("^h[a-z]{1,3}o\\b.*")); } }
练习:匹配空白行合email地址
拿到一篇文章, 如何判断里面有多少个空白行? 用正则表达式能方便地进行匹配, 注意空白行中可能包括空格, 制表符等。
p(" \n".matches("^[\\s&&[^\n]]*\\n$"));
解释: ^[\\s&&[^\n]]*
是空格符号但不是换行符, \\n$
最后以换行符结束
下面是匹配邮箱:
p("liuyj24@126.com".matches("[\\w[.-]]+@[\\w[.-]]+\\.[\\w]+"));
解释: [\\w[.-]]+
以一个或多个数字字母下划线.
或-
组成, @
接着是个@符号, 然后同样是[\\w[.-]]+
, 接着\\.
匹配.
, 最后同样是[\\w]+
Matcher类的matches()
,find()
和lookingAt()
matches()
方法会将整个字符串与模板进行匹配.
find()
则是从当前位置开始进行匹配, 如果传入字符串后首先进行find()
, 那么当前位置就是字符串的开头, 对当前位置的具体分析可以看下面的代码示例
lookingAt()
方法会从字符串的开头进行匹配.
public class Demo8 { private static void p(Object o){ System.out.println(o); } public static void main(String[] args) { Pattern pattern = Pattern.compile("\\d{3,5}"); String s = "123-34345-234-00"; Matcher m = pattern.matcher(s); //先演示matches(), 与整个字符串匹配. p(m.matches()); //结果为false, 显然要匹配3~5个数字会在-处匹配失败 //然后演示find(), 先使用reset()方法把当前位置设置为字符串的开头 m.reset(); p(m.find());//true 匹配123成功 p(m.find());//true 匹配34345成功 p(m.find());//true 匹配234成功 p(m.find());//false 匹配00失败 //下面我们演示不在matches()使用reset(), 看看当前位置的变化 m.reset();//先重置 p(m.matches());//false 匹配整个字符串失败, 当前位置来到- p(m.find());// true 匹配34345成功 p(m.find());// true 匹配234成功 p(m.find());// false 匹配00始边 p(m.find());// false 没有东西匹配, 失败 //演示lookingAt(), 从头开始找 p(m.lookingAt());//true 找到123, 成功 } }
Matcher类中的start()
和end()
如果一次匹配成功的话start()
用于返回匹配开始的位置, end()
用于返回匹配结束字符的后面一个位置
public class Demo9 { private static void p(Object o){ System.out.println(o); } public static void main(String[] args) { Pattern pattern = Pattern.compile("\\d{3,5}"); String s = "123-34345-234-00"; Matcher m = pattern.matcher(s); p(m.find());//true 匹配123成功 p("start: " + m.start() + " - end:" + m.end()); p(m.find());//true 匹配34345成功 p("start: " + m.start() + " - end:" + m.end()); p(m.find());//true 匹配234成功 p("start: " + m.start() + " - end:" + m.end()); p(m.find());//false 匹配00失败 try { p("start: " + m.start() + " - end:" + m.end()); }catch (Exception e){ System.out.println("报错了..."); } p(m.lookingAt()); p("start: " + m.start() + " - end:" + m.end()); } } //输出结果 true start: 0 - end:3 true start: 4 - end:9 true start: 10 - end:13 false 报错了... true start: 0 - end:3
替换字符串
想要替换字符串首先要找到被替换的字符串, 这里要新介绍Matcher
类中的一个方法group()
, 它能返回匹配到的字符串.
下面我们看一个例子, 把字符串中的java
转换为大写.
public class Demo10 { private static void p(Object o){ System.out.println(o); } public static void main(String[] args) { Pattern p = Pattern.compile("java"); Matcher m = p.matcher("java Java JAVA JAva I love Java and you"); p(m.replaceAll("JAVA"));//replaceAll()方法会替换所有匹配到的字符串 } } //输出结果 JAVA Java JAVA JAva I love Java and you
升级: 不区分大小写查找并替换字符串
为了在匹配的时候不区分大小写, 我们要在创建模板模板时指定大小写不敏感
public static void main(String[] args) { Pattern p = Pattern.compile("java", Pattern.CASE_INSENSITIVE);//指定为大小写不敏感的 Matcher m = p.matcher("java Java JAVA JAva I love Java and you"); p(m.replaceAll("JAVA")); } //输出结果 JAVA JAVA JAVA JAVA I love JAVA and you
再升级: 不区分大小写, 替换查找到的指定字符串
这里演示把查找到第奇数个字符串转换为大写, 第偶数个转换为小写
这里会引入Matcher
类中一个强大的方法appendReplacement(StringBuffer sb, String replacement)
, 它需要传入一个StringBuffer进行字符串拼接.
public static void main(String[] args) { Pattern p = Pattern.compile("java", Pattern.CASE_INSENSITIVE); Matcher m = p.matcher("java Java JAVA JAva I love Java and you ?"); StringBuffer sb = new StringBuffer(); int index = 1; while(m.find()){ //m.appendReplacement(sb, (index++ & 1) == 0 ? "java" : "JAVA"); 较为简洁的写法 if((index & 1) == 0){//偶数 m.appendReplacement(sb, "java"); }else{ m.appendReplacement(sb, "JAVA"); } index++; } m.appendTail(sb);//把剩余的字符串加入 p(sb); } //输出结果 JAVA java JAVA java I love JAVA and you ?