/*
*正则表达式(Regex):符合一定规则的表达式
*
*作用:用于专门操作字符串
*
*特点:用一些特定的符号来表示一些代码操作,这样就简化书写,所以学习正则表达式,就是在学习一些特殊符号的使用
*
*好处:可以简化对字符串的复杂操作
*
*弊端:符号定义越多,正则越长,阅读性越差
*如:((())())从左向右数左括号,共四组
*
*具体操作功能:
*1、匹配:String matches方法。用规则匹配整个字符串,只要有一处不符合规则,就匹配结束,返回false
*
*2、切割:String split();
*
*3、替换:String replaceAll();
*
*4、获取:将字符串中符合规则的字符串取出
* 操作步骤:
* 1、将正则表达式封装成对象
* 2、让正则对象和要操作的字符串相关联
* 3、关联后获取正则匹配引擎
* 4、通过引擎对符合规则的字串儿进行操作,比如取出
*/
/* 1、匹配:
* * 匹配前面的子表达式零次或多次(大于等于0次)。例如,zo*能匹配"z"以及"zoo"。*等价于{0,}。
* + 匹配前面的子表达式一次或多次(大于等于1次)。例如,"zo+"能匹配"zo"以及"zoo",但不能匹配"z"。+等价于{1,}。
*
* 对QQ号码进行校验
* 要求5~15位,0不能开头,只能是数字
*/
class RegexDemo
{
public static void main(String[] args)
{
checkQQ();
}
public static void checkQQ()
{
String qq="12345";
int len=qq.length();
if(len>=5 && len<=15)
{
if(!qq.startsWith("0"))
{
char[] arr=qq.toCharArray();
boolean flag=false;
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("长度错误");
}
}
}
//但以上写法太麻烦,所以可以改写为以下形式:
class RegexDemo1
{
public static void main(String[] args)
{
checkQQ();
}
public static void checkQQ()
{
String qq="12345";
int len=qq.length();
if(len>=5 && len<=15)
{
if(!qq.startsWith("0"))
{
try
{
long l=Long.parseLong(qq);
System.out.println("qq:"+1);
}
catch(NumberFormatException e)
{
System.out.println("出现非法字符.......");
}
}
else
{
System.out.println("不可以以0开头");
}
}
else
{
System.out.println("长度错误");
}
}
}
/*
* 以上这种方式,使用了String类中的方法,进行组合完成了需求,但是代码过于复杂,所以我们可以将以上写法改写成正则表达式:
*/
class RegexDemo2
{
public static void main(String[] args)
{
checkQQ();
}
public static void checkQQ()
{
String qq="12345";
/*
* 数字第一位是1-9之间的数
* 数字第二位是0-9之间的数
* 第二位数字出现4-14次
*/
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+"....不合法");
}
}
/*
*[abc]:表示字符串中只能有一个字符,并且第一位必须是a或b或c中的一个,如果有则返回true,如果没有则返回false
*/
class RegexDemo3
{
public static void main(String[] args)
{
demo();
}
public static void demo()
{
String str="a";
//[abc]:a、b 或 c(简单类)
String regex="[bcd]";
boolean b=str.matches(regex);
System.out.println(b);
}
}
/*
* 运行结果为:
* false
*
* 如果将"a"换成"b",则运行结果为:true
*
* 如果将"a"换成"bd",则运行结果为:false,因为只能规定一个字符
*/
class RegexDemo25
{
public static void main(String[] args)
{
demo();
}
public static void demo()
{
String str="be";
String regex="[bcd][a-z]";
boolean b=str.matches(regex);
System.out.println(b);
}
}
/*
* 运行结果为:
* true
*/
/*
* [^abc]:除了a、b、c以外的任何字符
*
* \d:数字[0-9]
* \D:非数字[^0-9]
*/
class RegexDemo4
{
public static void main(String[] args)
{
demo();
}
public static void demo()
{
String str="b9";
/*也可以写为:
* String reg="[a-zA-Z][0-9]";*/
String regex="[a-zA-Z]\\d";//不可以只写"\d",因为"\"是一个转义字符,会把"\"和"d"拆开理解,所以要写成"\\d"
boolean b=str.matches(regex);
System.out.println(b);
}
}
/*
* 运行结果为:
* true
*/
/*
* X?:X代表规则,X?代表紧靠该符号左边的规则出现1次或0次
* X*:X代表规则,X*代表紧靠该符号左边的规则出现0次或多次
* X+:X代表规则,X+代表紧靠该符号左边的规则出现1次或多次
*/
class RegexDemo5
{
public static void main(String[] args)
{
demo();
}
public static void demo()
{
String str="b9";
String reg="[a-zA-Z]\\d?";
boolean b=str.matches(reg);
System.out.println(b);
}
}
/*
* 运行结果为:
* true
*/
//X*:代表0次或多次
class RegexDemo6
{
public static void main(String[] args)
{
demo();
}
public static void demo()
{
String str="b9453";
String reg="[a-zA-Z]\\d*";
boolean b=str.matches(reg);
System.out.println(b);
}
}
/*
* 运行结果为:
* true
*/
/*
* X{n}:恰好n次
* X{n,}:至少n次
* X{n,m}:至少n次,但不超过m次
*/
class RegexDemo7
{
public static void main(String[] args)
{
demo();
}
public static void demo()
{
String qq="1239453";
//这里的[1-9]表示字符串第一个数字是"1-9"之间的数
//这里的"\d{4,14}表示除了第一位出现"4-14"位的数字
String regex="[1-9]\\d{4,14}";
boolean flag=qq.matches(regex);
if(flag)
System.out.println(qq+"....is ok");
else
System.out.println(qq+"....不合法");
}
}
/*
* 运行结果为:
* 1239453....is ok
*/
/*
* 练习:
* 匹配后继号段只有 13xxx 15xxx 18xxxx
*/
class RegexDemo8
{
public static void main(String[] args)
{
checkTel();
}
public static void checkTel()
{
String tel="18511340086";
String telReg="1[358]\\d{9}";
boolean flag=tel.matches(telReg);
if(flag)
System.out.println(tel+"....is ok");
else
System.out.println(tel+"....不合法");
}
}
/*
* 运行结果为:
* 18511340086....is ok
*/
//2、切割:split
class RegexDemo9
{
public static void main(String[] args)
{
splitDemo();
}
public static void splitDemo()
{
String str="zhangsan,lisi,wangwu";
String reg=",";
String[] arr=str.split(reg);
for(String s:arr)
{
System.out.println(s);
}
}
}
/*
* 运行结果为:
* zhangsan
* lisi
* wangwu
*/
class RegexDemo10
{
public static void main(String[] args)
{
splitDemo();
}
public static void splitDemo()
{
String str="zhangsan lisi wangwu";
String reg=" +";//按照多个空格来进行切割
String[] arr=str.split(reg);
System.out.println(arr.length);
for(String s:arr)
{
System.out.println(s);
}
}
}
/*
* 运行结果为:
* 3
* zhangsan
* lisi
* wangwu
*/
class RegexDemo11
{
public static void main(String[] args)
{
splitDemo();
}
public static void splitDemo()
{
String str="zhangsan.lisi.wangwu";
String reg="\\.";//"."在正则表达式中是一个特殊字符,想要切割".",就要转译一下,写为"\\."
String[] arr=str.split(reg);
System.out.println(arr.length);
for(String s:arr)
{
System.out.println(s);
}
}
}
/*
* 运行结果为:
* 3
* zhangsan
* lisi
* wangwu
*/
class RegexDemo12
{
public static void main(String[] args)
{
splitDemo("c:\\abc\\a.txt","\\\\");//当按"\\"切时,每一个"\"都需要转译,所以用"\\\\"
}
public static void splitDemo(String str,String reg)
{
String[] arr=str.split(reg);
System.out.println(arr.length);
for(String s:arr)
{
System.out.println(s);
}
}
}
/*
* 运行结果为:
* 3
* c:
* abc
* a.txt
*/
/*
* 按照叠词进行切割
* (.):表示任意字符
* \\1:表示与第一组字符相同
*/
class RegexDemo13
{
public static void main(String[] args)
{
splitDemo("erkkdyqquizzo","(.)\\1");
}
public static void splitDemo(String str,String reg)
{
String[] arr=str.split(reg);
System.out.println(arr.length);
for(String s:arr)
{
System.out.println(s);
}
}
}
/*
* 运行结果为:
* 4
* er
* dy
* ui
* o
*/
/*
* 按照多个叠词进行切割
* (.):表示任意字符
* \\1+:表示与第一组字符相同
*/
class RegexDemo14
{
public static void main(String[] args)
{
splitDemo("erkkkkkdyqquizzzo","(.)\\1+");//按叠字完成切割。为了可以让规则的结果被重用,
//可以将规则封装成一个组,用()完成。组的出现都有编号
//从1开始,想要使用已有的组可以通过\n(n就是组的编号)的形式来获取
}
public static void splitDemo(String str,String reg)
{
String[] arr=str.split(reg);
System.out.println(arr.length);
for(String s:arr)
{
System.out.println(s);
}
}
}
/*
* 运行结果为:
* 4
* er
* dy
* ui
* o
*/
//3、替换
class RegexDemo15
{
public static void main(String[] args)
{
//将字符串中的数组替换成#。
String str="wer1389980000ty1234564uiod234345675f";
replaceAllDemo(str,"\\d{5,}","#");//将数字连续超过5个的数组替换成#
}
public static void replaceAllDemo(String str,String reg,String newStr)
{
str=str.replaceAll(reg,newStr);
System.out.println(str);
}
}
/*
* 运行结果为:
* wer#ty#uiod#f
*/
class RegexDemo16
{
public static void main(String[] args)
{
String str="erkktyqqquizzzzzo";//将多个叠词替换成&。
replaceAllDemo(str,"(.)\\1+","&");//将多个叠词替换成&。不能替换成$,因为他是特殊字符
}
public static void replaceAllDemo(String str,String reg,String newStr)
{
str=str.replaceAll(reg,newStr);
System.out.println(str);
}
}
/*
* 运行结果为:
* er&ty&ui&o
*/
class RegexDemo17
{
public static void main(String[] args)
{
String str="erkktyqqquizzzzzo";//将重叠的字母替换成单个字母。如:zzzzz->z。
replaceAllDemo(str,"(.)\\1+","$1");//$代表前一个规则中的组,$1代表前一个规则中的第一个组
}
public static void replaceAllDemo(String str,String reg,String newStr)
{
str=str.replaceAll(reg,newStr);
System.out.println(str);
}
}
/*
* 运行结果为:
* erktyquizo
*/
/*
* 4、获取:将字符串中符合规则的字符串取出
* 操作步骤:
* 1、将正则表达式封装成对象
* 2、让正则对象和要操作的字符串相关联
* 3、关联后获取正则匹配引擎
* 4、通过引擎对符合规则的子串儿进行操作,比如取出
*
* Pattern类:正则表达式的编译表示形式,他可以描述正则表达式进行封装
* compile(String regex):将给定的正则表达式编译到模式中
*/
class RegexDemo18
{
public static void main(String[] args)
{
getDemo();
}
public static void getDemo()
{
String str="123456";
String reg="[1-9]\\d{4,14}";
//将规则封装成对象
Pattern p=Pattern.compile(reg);
//让正则对象和要作用的字符串相关联
Matcher m=p.matcher(str);
/* 其实String类中的matches方法用的就是Pattern和Matcher方法用的就是Pattern和Matcher对象来完成的
* 只不过被String的方法封装后,用起来较为简单,但是功能却单一*/
System.out.println(m.matches());
}
}
/*
* 运行结果为:
* true
*/
//找出一下字符串中连续三个字母组成的单词
class RegexDemo19
{
public static void main(String[] args)
{
getDemo();
}
public static void getDemo()
{
String str="ming tian jiu yao fang jia le,da jia";
String reg="[a-z]{3}";
//将规则封装成对象
Pattern p=Pattern.compile(reg);
//让正则对象和要作用的字符串相关联
Matcher m=p.matcher(str);
//find()将规则作用在字符串上,并进行符合规则的子串查找
boolean b=m.find();
System.out.println(b);
/*group()用于获取匹配后的结果,如果前面不写find()方法则获取失败,
*因为find()方法是匹配,不写find()就是没有匹配过,怎么会获取呢?*/
System.out.println(m.group());
}
}
/* 运行结果为:
* true
* min
* 取出了min,但以上写法,一次只能找到一组,改为:
*/
class RegexDemo29
{
public static void main(String[] args)
{
getDemo();
}
public static void getDemo()
{
String str="ming tian jiu yao fang jia le,da jia";
String reg="[a-z]{3}";
//将规则封装成对象
Pattern p=Pattern.compile(reg);
//让正则对象和要作用的字符串相关联
Matcher m=p.matcher(str);
boolean b=m.find();
System.out.println(b);
System.out.println(m.group());
boolean b1=m.find();
System.out.println(b1);
System.out.println(m.group());
}
}
/*
* 运行结果为:
* true
* min
* true
* tia
*
* 发现类似迭代器,先找,找到了取出,再找,找到再取出……,想要一次都找出来就需要写循环:
*/
class RegexDemo20
{
public static void main(String[] args)
{
getDemo();
}
public static void getDemo()
{
String str="ming tian jiu yao fang jia le,da jia";
String reg="[a-z]{3}";
//将规则封装成对象
Pattern p=Pattern.compile(reg);
//让正则对象和要作用的字符串相关联
Matcher m=p.matcher(str);
while(m.find())
{
System.out.println(m.group());
}
}
}
/* 运行结果为:
* min
* tia
* jiu
* yao
* fan
* jia
* jia
*
* 发现以上代码虽然取出了连续三个字母的组,但这些组并不都是单词,所以改写为:
* "\b":单词边界
* "\B":非单词边界
*/
class RegexDemo21
{
public static void main(String[] args)
{
getDemo();
}
public static void getDemo()
{
String str="ming tian jiu yao fang jia le,da jia";
String reg="\\b[a-z]{3}\\b";
//将规则封装成对象
Pattern p=Pattern.compile(reg);
//让正则对象和要作用的字符串相关联
Matcher m=p.matcher(str);
while(m.find())
{
System.out.println(m.group());
System.out.println(m.start()+"..."+m.end());//找到获取单词所在的位置,包含头不包含尾
}
}
}
/*
* 运行结果为:
* jiu
* 10...13
* yao
* 14...17
* jia
* 23...26
* jia
* 33...36
*/
class RegexDemo30
{
public static void main(String[] args)
{
getDemo();
}
public static void getDemo()
{
String str="ming tian jiu yao fang jia le,da jia";
String reg="\\b[a-z]{3}\\b";
//将规则封装成对象
Pattern p=Pattern.compile(reg);
//让正则对象和要作用的字符串相关联
Matcher m=p.matcher(str);
System.out.println("matches:"+m.matches());
while(m.find())
{
System.out.println(m.group());
System.out.println(m.start()+"..."+m.end());//找到获取单词所在的位置,包含头不包含尾
}
}
}
/*
* 运行结果为:?
* matches:false
* jiu
* 10...13
* yao
* 14...17
* jia
* 23...26
* jia
* 33...36
*/
/*
* 需求:
* 将下列字符串转成:我要学编程
*
* 到底用四种功能中的哪一个呢?或者哪几个呢?
* 思路方式:
* 1、如果只想知道该字符串是对是错,可以使用匹配。
* 2、想要将已有的字符串变成另一个字符串,替换
* 3、想要按照自己的方式将字符串变成多个字符串。切割,获取规则以外的子串
* 4、想要拿到符合要求的字符串子串,获取,获取符合规则的子串
*/
class RegexDemo22
{
public static void main(String[] args)
{
test_1();
}
public static void test_1()
{
String str="我我...我我...我要...要要...要要...学学学...学学...编编编...编程...程..程程..程";
/*
* 将已有字符串变成另一个字符串。使用替换功能
* 1、可以先将"."去掉。
* 2、再将多个重复的内容变成单个内容。
*/
str=str.replaceAll("\\.+","");
System.out.println(str);
str=str.replaceAll("(.)\\1+","$1");
System.out.println(str);
}
}
/*
* 运行结果为:
* 我我我我我要要要要要学学学学学编编编编程程程程程
* 我要学编程
*/
/*
* 192.68.1.254 102.49.23.13 10.10.10.10 2.2.2.2 8.109.90.30
* 将ip地址进行地址段顺序的排序
*
* 还按照字符串自然顺序排序,只要让他们每一段都是3位即可
* 1、按照每一段需要的最多的0进行补齐,那么每一段就会至少保证有3位
* 2、将每一段只保留3位。这样,所有的ip地址都是每一段3位
*/
class RegexDemo23
{
public static void main(String[] args)
{
ipSort();
}
public static void ipSort()
{
String ip="192.68.1.254 102.49.23.13 10.10.10.10 2.2.2.2 8.109.90.30";
ip=ip.replaceAll("(\\d+)","00$1");
System.out.println(ip);
ip=ip.replaceAll("0*(\\d{3})","$1");//"0*"代表没有0或有多个0
System.out.println(ip);
String[] arr=ip.split(" ");
TreeSet<String> ts=new TreeSet<String>();
for(String s:arr)
{
ts.add(s);
}
for(String s:ts)
{
System.out.println(s.replaceAll("0*(\\d+)","$1"));//将所有0都去掉
}
}
}
/*
* 运行结果为:
* 00192.0068.001.00254 00102.0049.0023.0013 0010.0010.0010.0010 002.002.002.002 008.00109.0090.0030
* 192.068.001.254 102.049.023.013 010.010.010.010 002.002.002.002 008.109.090.030
* 2.2.2.2
* 8.109.90.30
* 10.10.10.10
* 102.49.23.13
* 192.68.1.254
*/
/*
* 需求:对邮件地址进行校验
*/
class RegexDemo24
{
public static void main(String[] args)
{
checkMail();
}
public static void checkMail()
{
String mail="abc12@sina.com.cn";
String reg="[a-zA-Z0-9_]+@[a-zA-Z0-9]+(\\.[a-zA-Z]+){1,3}";//较为精确的匹配
//\w:匹配包括下划线的任何单词字符。等价于“[A-Za-z0-9_]”。
//String reg="\\w+@\\w+(\\.\\w+)+";//不太精确的匹配,124@12.4也会匹配,所以是不太精确的匹配
System.out.println(mail.matches(reg));
}
}
/*
* 运行结果为:
* true
*/
/*
* 网页爬虫(蜘蛛)
*/
/*
* 获取指定文档中的邮件地址
* 使用获取功能:Pattern Matcher
*/
class RegexTest
{
public static void main(String[] args)throws Exception
{
getMail();
}
public static void getMail()throws Exception
{
//"mail.txt"是有很多文件名、地址明、邮箱名的一个文件
BufferedReader bufr=new BufferedReader(new FileReader("mail.txt"));
String line=null;
String mailreg="\\w+@\\w+(\\.\\w+)+";
Pattern p=Pattern.compile(mailreg);
while((line=bufr.readLine())!=null)
{
Matcher m=p.matcher(line);
while(m.find())
{
System.out.println(m.group());
}
}
}
}
/*
*在网页上怎么获取邮箱
*/
class RegexTest1
{
public static void main(String[] args)throws Exception
{
getMail_1();
}
public static void getMail_1()throws Exception
{
URL url=new URL("http://tieba.baidu.com/p/2169646694");
URLConnection conn=url.openConnection();
BufferedReader bufIn=new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line=null;
String mailreg="\\w+@\\w+(\\.\\w+)+";
Pattern p=Pattern.compile(mailreg);
while((line=bufIn.readLine())!=null)
{
Matcher m=p.matcher(line);
while(m.find())
{
System.out.println(m.group());
}
}
}
}