正则表达式
视频1:01-正则表达式-概述&常见功能
正则表达式:专门用于操作字符串的技术。而且可以简化代码,用于对字符串进行复杂操作。
通过一些符号的形式来简化代码的书写,其实底层对应的还是代码。
弊端:符号太多,阅读性差。
所以,学习正则,先要学习一些符号。
正则对字符串大的常见操作功能:
1. 匹配
2. 切割
3. 替换
4. 获取
例子:
1. 对QQ号进行校验
2. 要求:5-15位,0不可以开头,必须都是数字。
public boolean matches(String regex)告知此字符串是否匹配给定的正则表达式。
String qq=”1235343k343”;
booleanb=qq.matches(“[1-9][0-9]{4-14}”);
System.out.println(qq+”:”+b);
视频2:02-正则表达式-符号
遇到反斜杠要输入两次反斜杠
x | 字符 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] | ||||
边界匹配器 | |||||
^ | 行的开头 | ||||
$ | 行的结尾 | ||||
\b | 单词边界 | ||||
\B | 非单词边界 | ||||
\A | 输入的开头 | ||||
\G | 上一个匹配的结尾 | ||||
\Z | 输入的结尾,仅用于最后的结束符(如果有的话) | ||||
\z | 输入的结尾 | ||||
Greedy 数量词 | |||||
X? | X,一次或一次也没有 | ||||
X* | X,零次或多次 | ||||
X+ | X,一次或多次 | ||||
X{n} | X,恰好 n 次 | ||||
X{n,} | X,至少 n 次 | ||||
X{n,m} | X,至少 n 次,但是不超过 m 次 |
正则对字符串大的常见操作功能:
匹配
使用String类中的matches方法;
StringphoneNumber=”18212343217”;
Stringregex=”1[358]\\d{9}”;
booleanb= phoneNumber.matches(regex);
System.out.println(phoneNumber+”:”+b);
切割
public String[] split(String regex,int limit)
根据匹配给定的正则表达式来拆分此字符串。
//例一
String str=”zhangsan lisi wangwu”;
String regex=” +”;
String[] strs=str.split(regex);
for(String s: strs)
{System.out.println(“-”+s+”-”);}
//例二
tring str=”zhangsan.lisi.wangwu”;
String regex=”\\.”; //这里只打一个.是没用的,因为.在正则里面代表任意字符
String strs=str.split(regex);
for(String s: strs)
{System.out.println(“-”+s+”-”);}
//例三,连续重复的叠词进行分割
//正则规则的复用,想复用,先封装,正则封装用()完成,封装完成后有编号,从1开始。正则中被()封装的称之为组,直接通过编号就可以调用对应的组。调用方式就是写已有的组的编号前加上\\ 如:\\1,在使用已有第一组的内容。原则:先有组,才可以使用对应的编号调用。
(A)(B)(C)(D)\\1\\3\\2\\4 表示:ABCDACBD
((A)(B(C)))这个有多少组? 数左括号,按左括号编号
1组 | ((A)(B(C))) | |
2组 | A | |
3组 | (B(C)) | |
4组 | (C) | |
没有打左括号,整个就是一个组,编号位0 |
|
String str=”ert###yuixkkkkcvbn”;
String regex=”(.)\\1+”;
String strs=str.split(regex);
for(String s: strs)
{System.out.println(“-”+s+”-”);}
替换
public String replaceAll(String regex,String replacement)
使用给定的 replacement 替换此字符串所有匹配给定的正则表达式的子字符串。
public String replaceFirst(String regex,String replacement)
使用给定的 replacement 替换此字符串匹配给定的正则表达式的第一个子字符串。
//public String replace(char oldChar, char newChar)
//public String replace(CharSequence target,CharSequence replacement)
//例一:叠词用一个#替换
String str=”wert####yuios@@@@@@@@dfgh”;
Str=str.replaceAll(”(.)\\1+”,”#”);
System.out.println(str);
//例二:叠词用叠词第一个字符替换
String str=”wert####yuios#####dfgh”;
Str=str.replaceAll(”(.)\\1+”,”$1”);//在参数列表中,其他参数要使用前一个参数中的规则的组,需要用$加组编号,例如$1
System.out.println(str);
//例三:号码中间的四位数字用****替换
String str=”18612345678”;
//方法:分组,将前三位数字分组为1,后四位数字分组为2
Str=str.replaceAll(”(\\d{3})\\d{4}(\\d{4})”,”$1****$2”);
System.out.println(str);
//例四:论坛屏蔽QQ号,电话号码,银行卡号等 但类似这样的:QQ:衣尔散思。。。就没办法了
String str=”芳龄:20,QQ号:99999999999fghjkl87772374232742739342rtewqsaf”; //连续5个以上数字就用***替换
Str=str.replaceAll(”\\d{5,} ”,”***”);
System.out.println(str);
获取
//以上三个功能内部都是Pattern正则表达式对象。现在需要其他功能时,字符串String类中没有对应的方法,只能找Pattern对象(查看API);
/*
Pattern对象的使用原理:
1. 将正则表达式字符串编译成正则对象pattern
2. 通过pattern对象获取Matcher对象(匹配器对象)
3. 通过匹配器对象对字符串进行规则的匹配,结果都在匹配器中
4. 通过匹配器对象的功能获取结果。
5. 范例代码:
Patternp=Pattern.compile(”a*b”);
Matcherm=p.matcher(“aaaaab”);
Booleanb=m.maches();
在仅使用一次正则表达式时,可以方便地通过此类定义matches 方法。此方法编译表达式并在单个调用中将输入序列与其匹配。语句
boolean b =Pattern.matches("a*b", "aaaaab");
等效于上面的三个语句,尽管对于重复的匹配而言它效率不高,因为它不允许重用已编译的模式。
*/
Stringstr="da jia zhu yi le, ming tian fang jiale!";
String regex="\\b[a-zA-Z]{3}\\b"; //取出由3个字母组成的单词,\\b表示单词边界,否则ming的前三个字母组成的min也将被输出
Pattern p=Pattern.compile(regex);
Matcher m=p.matcher(str);
booleanb=m.matches();
System.out.println(b);
while(m.find())
{
System.out.println(m.group()+".."+ m.start()+"--"+m.end());
System.out.println(str.substring(m.start(),m.end()));
}
import java.lang.reflect.Array;
importjava.util.Arrays;
publicclass ReduplicationDemo1
{
publicstaticvoid main(String[] args)
{
test1();
test2();
test3();
}
privatestaticvoid test3()
{
/*
* 案例三:对邮箱地址进行校验
*/
String mail="itcast2013@itcast.cn";
//精准校验
String regex="[a-zA-Z0-9_]+@[a-zA-Z0-9-]+(\\.[a-zA-Z]{2,3}){1,3}";
booleanb=mail.matches(regex);
System.out.println(mail+":"+b);
//笼统校验
regex="\\w+@\\W+(\\.\\w+)+";
}
privatestaticvoid test2()
{
/*
*案例二:
*"23.12.10.5 192.168.100.322 3.3.3.3 10.10.10.10 "
*要求将这些ip按照顺序排序。
*
*思路:
*1.将ip通过空格切割
*2.对ip进行排序,通过字符串字典顺序排序,这个顺序是错的
* 原因:每个ip有四段,每一段最多三位,应该按照位数比较才是对的,否则192 与 3 就是百位与个位的数相比
* 所以应该每一段都补足三位,不满足的用0填充,这样比较字典顺序才是对的
* 怎么补0呢?每一段的位数都不同,补0的个数也不一样。
* 技巧:干脆按照所需的最多的0的个数来补,每一段都补两个0
* 有的地址段超出了三位,取每一段的最后三位
* 排序完后,有的地址前面多了0,去掉前面的0
*/
String ip_str="23.12.10.5 192.168.100.322 3.3.3.3 10.10.10.10 ";
ip_str=ip_str.replaceAll("(\\d+)", "00$1"); //每一段补两个0
System.out.println(ip_str); //0023.0012.0010.005 00192.00168.00100.00322 003.003.003.003 0010.0010.0010.0010
ip_str=ip_str.replaceAll("0*(\\d{3})", "$1"); //取每一段的最后三位,
X* | X,零次或多次 |
String[] ips=ip_str.split(" +");
Arrays.sort(ips);
for(String s:ips)
{
System.out.println(s.replaceAll("0*(\\d+)", "$1")); //去掉前面的0
}
}
privatestaticvoid test1()
{
/*
*案例一:我我....我..........我我...我我我....要要...要要...要要要.....学学..学学..学..学学学.学学学....学学学学软..软软......件件件..件件件件件.件
*实现:我要学软件
*
*思路:
*1.使用正则表达式
*2.先把所有的.去掉
*3.替换叠词。
*/
String str="我我....我..........我我...我我我....要要...要要...要要要.....学学..学学..学..学学学.学学学....学学学学软..软软......件件件..件件件件件.件";
String newStr=str.replaceAll("\\.+", "");
String str2=newStr.replaceAll("(.)\\1+", "$1");
System.out.println(str2);
}
}
importjava.io.BufferedReader;
importjava.io.File;
importjava.io.FileReader;
importjava.io.IOException;
importjava.io.InputStream;
import java.io.InputStreamReader;
importjava.net.URL;
importjava.net.URLConnection;
importjava.util.ArrayList;
importjava.util.List;
importjava.util.regex.Matcher;
importjava.util.regex.Pattern;
publicclass WebCrawlersDemo
{
publicstaticvoid main(String[] args) throws IOException
{
/*
* 网络爬虫:其实就是一个应用程序,获取网络中的指定信息(符合指定规则的信息)。
*
* 网络中的邮件地址。
*/
File file=new File("mail.txt");
String str="http://bbs.tianya.cn/post-enterprise-401802-1.shtml";
String regex="\\w+@\\w+(\\.\\w+)+";
//List<String> list=getMails(file,regex);
List<String> list=getMailByNet(str,regex);
for(String mail:list)
{
System.out.println(mail);
}
}
publicstatic List<String>getMailByNet(String str_url,String regex) throws IOException
{
//1.将str_url封装成URL对象。
URL url=new URL(str_url);
List<String> list=new ArrayList<String>();
//2.打开连接
URLConnection conn=url.openConnection();
//3,获取读取流
InputStream in=conn.getInputStream();
//封装成BufferedReader对象
BufferedReader bufr=new BufferedReader(newInputStreamReader(in));
Pattern p= Pattern.compile(regex);
String line=null;
while((line=bufr.readLine())!=null)
{
//System.out.println(line);
Matcher m=p.matcher(line);
while(m.find())
list.add(m.group());
}
bufr.close();
returnlist;
}
privatestatic List<String> getMails(Filefile, String regex) throws IOException
{
//1.读取文件
List<String> list=new ArrayList<String>();
BufferedReader bufr=new BufferedReader(new FileReader(file));
Pattern p= Pattern.compile(regex);
String line=null;
while((line=bufr.readLine())!=null)
{
//System.out.println(line);
Matcher m=p.matcher(line);
while(m.find())
list.add(m.group());
}
bufr.close();
returnlist;
}
}