1正则表达式——功能:匹配、切割、替换
正则表达式:符合一定规则的表达式。
作用:用于专门操作字符串。
特点:用一些特定的符号来表示一些代码操作,这样简化了书写。
所以学习正则表达式,就是在学习一些特殊符号的使用。
好处:可以简化对字符串的复杂操作。
弊端:符号定义越多,正则表达式越长,阅读性越差。
正则表达式功能:
1,匹配:String类中的matches方法。
matches(regex):用正则表达式的规则匹配整个字符串,只要有一处不符合规则,就匹配结束,返回false。
2,切割:String类中的split方法。
split(regex):根据正则表达式split进行切割当前字符串str。
3,替换:String类中的replaceAll方法。
replaceAll(regex,newStr):根据正则表达式的规则,用新字符串替换正则表达式定义的字符串。
2正则表达式规则
字符:
x字符x
\\反斜线字符
\0n带有八进制值0的字符n(0<=n<=7)
\0nn带有八进制值0的字符nn(0<=n<=7)
\0mnn带有八进制值0的字符mnn(0<=m<=3、0<=n<=7)
\xhh带有十六进制值0x的字符hh
\uhhhh带有十六进制值0x的字符hhhh
\t制表符('\u0009')
\n新行(换行)符('\u000A')
\r回车符('\u000D')
\f换页符('\u000C')
\a报警(bell)符('\u0007')
\b匹配一个单词边界,也就是指单词和空格间的位置
\e转义符('\u001B')
\cx对应于x的控制符
字符类:
[abc]a、b或c(简单类)
[^abc]任何字符,除了a、b或c(否定)
[a-zA-Z]a到z或A到Z,两头的字母包括在内(范围)
[a-d[m-p]]a到d或m到p:[a-dm-p](并集)
[a-z&&[def]]d、e或f(交集)
[a-z&&[^bc]]a到z,除了b和c:[ad-z](减去)
[a-z&&[^m-p]]a到z,而非m到p:[a-lq-z](减去)
预定义字符类:
.任何字符(与行结束符可能匹配也可能不匹配)
\d数字:[0-9]
\D非数字:[^0-9]
\s空白字符:[\t\n\x0B\f\r]
\S非空白字符:[^\s]
\w单词字符:[a-zA-Z_0-9]
\W非单词字符:[^\w]
Greedy数量词:
X?X,一次或一次也没有
X*X,零次或多次
X+X,一次或多次
X{n}X,恰好n次
X{n,}X,至少n次
X{n,m}X,至少n次,但是不超过m次。
3组和捕获及正则表达式实例
组合捕获
捕获组可以通过从左到右计算其开括号来编号。例如,在表达式((A)(B(C)))中,存在四个这样的组:
1((A)(B(C)))
2\A
3(B(C))
4(C)
组0始终代表整个表达式。
之所以这样命名捕获组是因为在匹配中,保存了与这些组匹配的输入序列的每个子序列。
捕获的子序列稍后可以通过Back引用在表达式中使用,也可以在匹配操作完成后从匹配器获取。
与组关联的捕获输入始终是与组最近匹配的子序列。如果由于量化的缘故再次计算了组,
则在第二次计算失败时将保留其以前捕获的值(如果有的话)例如,将字符串"aba"与表达式(a(b)?)+相匹配,
会将第二组设置为"b"。在每个匹配的开头,所有捕获的输入都会被丢弃。
以(?)开头的组是纯的非捕获组,它不捕获文本,也不针对组合计进行计数。
应用实例:
需求:对QQ号码进行校验,要求:5~15位,0不能开头,只能是数字。
原方式:这种方式使用String类中的方法,进行组合完成了需求。但是代码过于复杂。
代码示例:
class RegexDemo{ public static void main(String[] args){ checkQQ_1(); checkQQ(); demo(); splitDemo(); String str = "wer1389980000ty12345uiod2345452452454f";//将字符串中数字替换成# replaceAllDemo(str,"\\d{5,}","#"); //\\d{5,}:连续0到9的数字至少5个。 String strr = "erkktytuqqquizzzzzo"; //将叠词替换成相应的单个字符。 replaceAllDemo(strr,"(.)\\1+","$1");//$1 表示正则表达式中的第一组,即()中的内容,符号$有特殊含义。 } //根据正则表达式替换 public static void replaceAllDemo(String str,String regex,String newStr){ str = str.replaceAll(regex,newStr); //String类的replaceAll方法,可以用正则替换 System.out.println(str); } //根据正则表达式切割字符串 public static void splitDemo(){ /* String str = "zhangsan....lisi...wangwu"; String regex = "\\.+"; */ //按照多个点来切割,见正则中的Greedy数量词 String str = "crkkadfddalpezzzzkjgf"; String regex = "(.)\\1+"; //按照叠词完成切割,可以将规则封装成一个组,用()括起来。 //组的出现都有编号,从1开始。想要使用已有的组可以通过 \n的形式获取,n是编号 String[] arr = str.split(regex); //根据叠词分割 for(String s : arr){ System.out.println(s); } } //正则表达式定义规则:字符,字符类,预定义字符类,Greedy数量词 public static void demo(){ String str = "b9"; String regex = "[a-zA-Z]\\d"; boolean b = str.matches(regex); //匹配 System.out.println(b); } //正则表达式方式 //boolean matches(String regex); 告知此字符串是否匹配给定的正则表达式。 public static void checkQQ(){ String qq = "275150374"; String regex = "[1-9][0-9]{4,14}"; boolean flag = qq.matches(regex); //匹配 if(flag) System.out.println(qq+"...is ok"); else System.out.println(qq+"...不合法"); } //原方式,不使用正则表达式。 public static void checkQQ_1(){ String qq = "111111111111111"; int len = qq.length(); if(len>=5 && len<=15){ if(!qq.startsWith("0")){ char[] arr = qq.tocharArray(); boolean flag = true; for(int x=0; x<arr.length; x++){ if(!(arr[x]>='0' && arr[x]<='9')){ flag = false; break; } } if(flag) System.out.println("QQ: "+qq); else System.out.println("出现非法字符"); } else{ System.out.println("不能以0开头"); } } else{ System.out.println("长度错误"); } } }
4正则表达式功能——获取(匹配器Matcher)
获取:将字符串中的符合规则的子串取出。
操作步骤:
1,将正则表达式封装成对象。
2,让正则对象和要操作的字符串相关联。
3,关联后,获取正则匹配引擎。
4,通过引擎,对符合规则的子串进行操作,比如取出。
代码示例:
import java.util.regex.*; class RegexDemo2 { public static void main(String[] args){ getDemo(); } public static void getDemo(){ String str = "ming tian jiu yao fang jia la"; //正则表达式,\b是单词边界符。 String regex = "\\b[a-z]{4}\\b"; //将正则封装成对象。 Pattern p = Pattern.compile(regex); //让正则对象和要作用的字符串相关联。获取匹配器对象。 Matcher m = p.matcher(str); //str.matches(regex);//其实String类中的matches方法,用的就是Pattern和Matcher对象来完成的, //只不过被String的方法封装后,用起来较为简单,但是功能却单一。 while(m.find()){ //判断是否有符合匹配器的子串。 System.out.println(m.group()); //返回由以前匹配操作所匹配的输入子序列,返回匹配结果。 //匹配的子串的开始脚标和结束脚标,包含头不包含尾。 System.out.println("位置:"+m.start()+"..."+m.end()); } } }
匹配结果:
5正则表达式练习★
练习1:
需求:将下列字符串转换成:我要学编程
到底用四种功能中的哪一个呢?或者哪几个呢?
思路方式:
1,如果只想知道该字符是对还是错,使用匹配。
2,想要将已有的字符串变成另一个字符串,替换。
3,想要按照自定的方式将字符串变成多个字符串,切割、获取规则以外的子串。
4,想要拿到符合需求的字符串子串,获取、获取符合规则的子串。
练习2:
需求:将ip地址进行地址段顺序的排序。
192.68.1.254102.49.23.1310.10.10.102.2.2.28.109.30.90
还按照字符串自然顺序,只要让它们每一段都是3位即可。
1,按照每一段需要的最多的0进行补齐,那么每一段至少保证有3位。
2,将每一段只保留3位。这样,所有的ip地址段都是每一段3位。
练习3:
需求:对邮件地址进行校验。
代码示例:
import java.util.regex.*; import java.util.*; class RegexTest{ public static void main(String[] args){ test_1(); ipSort(); checkMail(); } public static void test_1(){ String str = "我我...我我...我要..要要...要要...学学学..学学..编编...编编..编程..程程.程程"; /* 将已有字符串变成另一个字符串。使用替换功能。 1,可以先将 “.”去掉。 2,再将多个重复的内容变成单个内容。 */ str = str.replaceAll("\\.+",""); System.out.println(str); //$1 表示正则表达式中的第一组,即()中的内容,符号$有特殊含义. str = str.replaceAll("(.)\\1+","$1"); System.out.println(str); } public static void ipSort(){ String ip = "192.68.1.254 102.49.23.13 10.10.10.10 2.2.2.2 8.109.30.90"; ip = ip.replaceAll("(\\d+)","00$1"); //每一段都补两个0 System.out.println(ip); ip = ip.replaceAll("0*(\\d{3})","$1"); //每一段保留三位 System.out.println(ip); String[] arr = ip.split(" "); TreeSet<String> ts = new TreeSet<String>(); //TreeSet集合,自然排序 for(String s : arr){ ts.add(s); } for(String s : ts){ System.out.println(s.replaceAll("0*(\\d+)","$1")); //把开头的0去掉 } } public static void checkMail(){ String mail = "abc123@sina.com"; String reg = "[a-zA-Z0-9_]+@[a-zA-Z0-9]+(\\.[a-zA-Z]+)+";//较为精确的匹配 String regex = "\\w+@\\w+(\\.\\w+)+"; //相对不太精确的匹配 System.out.println(mail.matches(regex)); } }
6抓取电子邮件地址和URL类
URL:java.net包的URL类、URLConnection类
调用URL对象的openConnection()方法创建连接对象,返回URLConnection对象。
URLConnection类中
getInputStream():返回从此打开的链接读取数据的读取流,读取URL资源。
getOutputStream():返回写入到此链接的输出流。
代码示例:
import java.util.regex.*; import java.io.*; import java.net.*; class RegexTest2 { public static void main(String[] args) throws Exception{ getMails(); getMails_1(); } //从文档中抓取电子邮件地址 public static void getMails() throws Exception{ BufferedReader bufr = new BufferedReader(new FileReader("e:\\mail.txt")); String mailregex = "\\w+@\\w+(\\.\\w+)+"; Pattern p = Pattern.compile(mailregex);//将正则封装成对象 String line = null; while((line=bufr.readLine())!=null){ Matcher m = p.matcher(line); //正则对象和字符串关联,获取匹配器 while(m.find()){ //是否有符合匹配器的子串。 System.out.println(m.group()); //返回匹配的子序列,返回匹配结果。 } } } //从网页中抓取电子邮件地址 public static void getMails_1() throws Exception{ URL url = new URL("http://192.168.0.100:8080/myweb/mail.html"); URLConnection conn = url.openConnection(); //创建连接对象。 BufferedReader bufIn = new BufferedReader(new InputStreamReader(conn.getInputStream())); //读取URL资源的读取流 String mailregex = "\\w+@\\w+(\\.\\w+)+"; Pattern p = Pattern.compile(mailregex); //把正则表达式封装成对象 String line = null; while((line=bufIn.readLine())!=null){ Matcher m = p.matcher(line); //创建匹配器,关联正则对象和字符串 while(m.find()){ //判断是否有匹配的子串 System.out.println(m.group()); //返回匹配结果 } } } }