------- android培训、java培训、期待与您交流! ----------
什么是正则表达式?
正则表达式:
符合一定规则的表达式
作用:用于专门操作字符串
特点:用一些特定的符号来表示一些代码操作,这样就简化书写。
所以学习正则表达式,就是在学习一些特殊符号的使用
好处: 可以简化字符串的复杂操作
弊端: 符号定义越多,正则越长,阅读性越差。
作用:用于专门操作字符串
特点:用一些特定的符号来表示一些代码操作,这样就简化书写。
所以学习正则表达式,就是在学习一些特殊符号的使用
好处: 可以简化字符串的复杂操作
弊端: 符号定义越多,正则越长,阅读性越差。
正则表达式的规则
具体操作功能
1,匹配:String matches()。用规则匹配整个字符串,只要有一处不符合规则,就匹配结束,返回false。
如:[a-zA-z]\\d*匹配b35可以匹配,但是匹配b35a就不可以匹配。因为一开始匹配b时,匹配成功,匹配35时匹配不成功,再匹配a时,就匹配不成功。
只要有一处不符合规则,则匹配不成功
2,替换:String replaceAll()
3,切割:String split(); (拿到规则以外的子串) 如:字符串是"abckkdefkkqwekk",如果规则是"kk",那么获取到的结果是abc,def,qwe
4,获取:将字符串中符合规则的字串取出 (拿到符合规则的子串)
操作步骤:
1,将正则表达式封装成对象
2,让正则对象和要操作的字符串相关联
3,关联后,获取正则匹配引擎
4,通过引擎,对符合规则的字串进行操作,比如取出
如:[a-zA-z]\\d*匹配b35可以匹配,但是匹配b35a就不可以匹配。因为一开始匹配b时,匹配成功,匹配35时匹配不成功,再匹配a时,就匹配不成功。
只要有一处不符合规则,则匹配不成功
2,替换:String replaceAll()
3,切割:String split(); (拿到规则以外的子串) 如:字符串是"abckkdefkkqwekk",如果规则是"kk",那么获取到的结果是abc,def,qwe
4,获取:将字符串中符合规则的字串取出 (拿到符合规则的子串)
操作步骤:
1,将正则表达式封装成对象
2,让正则对象和要操作的字符串相关联
3,关联后,获取正则匹配引擎
4,通过引擎,对符合规则的字串进行操作,比如取出
以上四种功能中,使用哪一个呢?
思路方式:
1,如果只想知道字符串是对是错,用匹配。
2,如果想将已有的字符串变成另一个字符串,用替换
3,如果按照指定的方式将字符串变成多个字符串,用切割。切割是获取规则以外的字串
4,如果想要拿到符合需求的字符串字串,用获取。获取时拿到符合规则的字串
思路方式:
1,如果只想知道字符串是对是错,用匹配。
2,如果想将已有的字符串变成另一个字符串,用替换
3,如果按照指定的方式将字符串变成多个字符串,用切割。切割是获取规则以外的字串
4,如果想要拿到符合需求的字符串字串,用获取。获取时拿到符合规则的字串
匹配:String matches方法。
/*
匹配:String matches方法。
需求:
对qq号进行校验 要求:1~15 0不能开头,只能是数字
*/
public class Demo {
public static void main(String[] args) throws Exception {
// function_1();
function_2();
}
//使用正则表达式
public static void function_2() {
String qq = "1233456666";
String regex = "[1-9][0-9]{4,14}";//规则是:第一位是1-9之间的数字。第二位是0-9之间,并且长度为4-14
boolean flag = qq.matches(regex);
if (flag)
System.out.println(qq + "正确");
else
System.out.println(qq + "格式错误");
}
//这种方式,使用了String类中的方法,进行组合完成了需求,但是代码过于复杂
public static void function_1() {
String qq = "1233456666";
if (!(qq.length() >= 5 && qq.length() <= 15)) {
System.out.println("长度必须 5 <= x <= 15");
return;
}
if (qq.charAt(0) == '0') {
System.out.println("首字母不能为0");
return;
}
// char chs[] = str.toCharArray();
// for (int i = 0; i < chs.length; i++) {
// if (!(chs[i] >= '0' && chs[i] <= '9')) {
// System.out.println("输入的不是数字");
// return;
// }
// }
try {
long l = Long.parseLong(qq);//不能使用Integer.parseInteger(qq)。因为qq的长度有可能超过int类型
} catch (Exception e) {
System.out.println("输入的不是数字");
return;
}
System.out.println("正确");
}
}
切割:String split()
/*
切割:String split();
*/
public class Demo {
public static void main(String[] args) throws Exception {
//splitDemo("abc def ghi", " ");//切割空格
//splitDemo("abc def ghi", " +");//切割一个或多个空格," +"代表一个或多个空格
//splitDemo("abc.def.ghi","\\.");//切割. ,因为.在正则表达式中代表任何字符,所以\.在正则表达式中代表. ,而转换到java中时需要\\.
//splitDemo("C:\\abc\\a.txt","\\\\");// 切割\\ ,在正则表达式中\\代表一个\,所以切割\\,需要使用\\\\
//splitDemo("abckkdefkkhikkg", "kk");//切割叠词 kk
//splitDemo("abcddefgghijj", "(.)\\1");//切割叠词dd,gg,gg。 为了可以让规则的结果被重用,可以将规则封装成一个数组。
//用()完成。组的出现都有编号,从1开始。想要使用已有的组,可以通过 \n (n就是组的编号)的形式获取
//在此例中, .代表任意字符,将.放在一个组中(.), (.)\\1 代表重用第1个组。
//既:如果.是一个字符k,那么(.)\\1,就代表重用第一个组中的k,那么(.)\\1相当于kk
//有多少个组,看左括号 "(" 的个数。
//如:((A)(B(C))) 代表4个组。第一个组是((A)(B(C))) 二组是(A) 三组(B(C)) 四组(C)
//想按照出现一对对的字符进行切割。例如,对ee进行切割,想获取到的结果为abe,esa,d。
//splitDemo("abeeesaeeeed","(ee)+");// (ee)代表对字符串ee,并封装进一个组中。(ee)+ 代表ee这个字符串出现一次或者多次都符合规则
//想按照出现一对对的字符进行切割。如:对ee和qq切割,想获取到的结果为abc,esa,d
//splitDemo("abeeesaqqqqd","((.)\\2)+");//此规则中有两个括号,里边的(.)代表任意字符,并存放在一个组中。(.)\\2代表重用括号里面的内容,
//如果括号中的.为e,那么(.)\\2代表ee。为什么此规则写的是(.)\\2而不是(.)\\1呢?
//因为,在整个规则中,是按左括号"("的个数来确定是第几组数的,在此规则中,因为(.)的左括号是整个规则中的第2个左括号,
//所以(.)是在第2组,所以(.)\\2代表重用的就是(.),那么(.)\\1代表重用的就是第一个左括号中的内容,既重用((.)\\2)
splitDemo("abcddddefgggggghijj", "(.)\\1+");//.这个任意字符是一个组,\\1是重用第一个组,+代表出现了1次或多次
}
//对特定的字符串进行切割
public static void splitDemo(String str,String regex) {
String[] ss = str.split(regex);
for(String s : ss){
System.out.println(s);
}
}
}
替换:String replaceAll()
/*
替换:String replaceAll();
*/
public class Demo {
public static void main(String[] args) throws Exception {
String str = "wef342523asfasdf563456ljlj6757asdf352435";//将字符串中出现至少5次的数字换成#
replaceAllDemo(str,"\\d{5,}","#");//wef#asfasdf#ljlj6757asdf#
String str1 = "abcddeffffghiiijkaakqq";//将字符串中的叠词替换成&
replaceAllDemo(str1,"(.)\\1+","&");//abc&e&gh&jk&k& ()代表组,.代表任意字符,\\1代表获取组中内容,
//如果.的字符是k,那么(.)代表将k视为一个组,\\1代表获取第一组中的内容,+代表出现1次或者多次,
//所以,(.)\\1+ 代表获取第一组中的字符,并且出现1次或者多次。
//如:(.)如果为k,那么(.)\\1代表kk,(.)\\1+ 代表kk出现1次或者多次
String str2 = "abcddeffffghiiijkaakqq";//将重叠的字符换成单个字符。kkkk --> k
replaceAllDemo(str2, "(.)\\1+", "$1");//abcdefghijkakq $1也代表获取第一组中的内容,$1与\\1不同,\\1是正则表达式中获取第一组,
// $1代表可以在正则表达式外获取第一组
}
//使用给定的 newStr 替换此字符串所有匹配给定的正则表达式的子字符串。
public static void replaceAllDemo(String str,String regex,String newStr) {
str = str.replaceAll(regex, newStr);
System.out.println(str);
}
}
获取:将字符串中符合规则的字串取出
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/*
获取:将字符串中符合规则的字串取出
操作步骤:
1,将正则表达式封装成对象
2,让正则对象和要操作的字符串相关联
3,关联后,获取正则匹配引擎
4,通过引擎,对符合规则的字串进行操作,比如取出
*/
public class Demo {
public static void main(String[] args) throws Exception {
getDemo();
}
public static void getDemo(){
String str = "ming tian yao fang jia le";
String regex = "\\b[a-z]{3}\\b";//英文字符连续出现3次的都符合规则,\\b代表单词边界。
//如果将边界\\b去掉,那么结果为min,tia,yao,fan,jia,因为一开始时,前3个单词就已经符合规则了
//将规则封装成对象
Pattern p = Pattern.compile(regex);
//让正则表达式和要作用的字符串相关联,并返回一个匹配器引擎
Matcher m = p.matcher(str);
//System.out.println(m.matches());//false 其实String类中的matches方法。用的就是Pattern和Matcher对象来完成的。
//只不过被String的方法封装后,用起来比较简单,但是功能比较单一
//boolean b = m.find();//将规则作用到字符串上,并进行符合规则的字串查找。
//System.out.println(b);//true
//System.out.println(m.group());//yao 用于获取匹配后的结果,但是只获取到一次就无法获取了,所以需要使用循环去获取
while(m.find()){//将规则作用到字符串上,并进行符合规则的字串查找
System.out.println(m.group());// yao jia 用于获取匹配后的结果,但是只获取到一次就无法获取了,所以需要使用循环去获取
}
}
}
练习
/*
练习:
匹配手机号码
13XXX 15XXX 18XXX
*/
public class Demo {
public static void main(String[] args) throws Exception {
function("13807569135");
}
public static void function(String str) {
String regex = "1[358]\\d{9}";//第一位是1,第二位3或5或8,后边9位是0-9之间的数字
boolean flag = str.matches(regex);
System.out.println(flag);
}
}
<pre name="code" class="java">/*
练习:
将下列字符串转成:我要编程
"我我...我我...我要...要...要要...学学学....学学...编编编...编程..程.程程...程...程"
*/
import java.util.Arrays;
import java.util.regex.*;
public class Demo {
public static void main(String[] args) throws Exception {
String str = "我我...我我...我要...要...要要...学学学....学学...编编编...编程..程.程程...程...程";
/*
将已有字符串变成一个字符串。使用 替换功能
思路:
1,可以先将 . 去掉
2,再将多个重复的内容变成单个内容
*/
str = str.replaceAll("\\.", "");//将 . 去掉
System.out.println(str);//我我我我我要要要要学学学学学编编编编程程程程程程
str = str.replaceAll("(.)\\1+", "$1");//将重复的内容变成单个内容
System.out.println(str);//我要学编程
}
}
/*
练习:
将一下ip地址进行地址段顺序的排序
"192.168.1.254 102.49.23.13 10.10.10.10 2.2.2.2 8.109.90.30"
排序后的结果为
2.2.2.2
8.109.90.30
10.10.10.10
102.49.23.13
192.168.1.254
*/
import java.util.Arrays;
import java.util.TreeSet;
import java.util.regex.*;
public class Demo {
public static void main(String[] args) throws Exception {
ipSort("192.168.1.254 102.49.23.13 10.10.10.10 2.2.2.2 8.109.90.30");
}
/*
思路:
需要按照字符串的自然顺序排序,只要让他们每一段都是3位即可
1,按照每一段需要的最多的0进行补齐,那么每一段就会至少保证有3位
2,将多余的0删除,使得每一段ip地址只保留3位
3,将ip地址进行排序
4,在ip地址中,将前边的0删除
*/
public static void ipSort(String ip){
ip = ip.replaceAll("(\\d+)", "00$1");//在每一个数字的前面补两个0
System.out.println(ip);//00192.00168.001.00254 00102.0049.0023.0013 0010.0010.0010.0010 002.002.002.002 008.00109.0090.0030
ip = ip.replaceAll("0*(\\d{3})", "$1");//为了保证都是三位数,将多余的0删除
System.out.println(ip);//192.168.001.254 102.049.023.013 010.010.010.010 002.002.002.002 008.109.090.030
String[] ips = ip.split(" +");//将一个到多个空格删除
TreeSet<String> ts = new TreeSet<String>();
for(String s : ips)
ts.add(s);
for(String s : ts){
System.out.println(s.replaceAll("0*(\\d+)","$1"));//将多余的0删除
/*
2.2.2.2
8.109.90.30
10.10.10.10
102.49.23.13
192.168.1.254
*/
}
}
}
/*
练习:
对邮件地址进行校验
*/
import java.util.Arrays;
import java.util.TreeSet;
import java.util.regex.*;
public class Demo {
public static void main(String[] args) throws Exception {
checkMail("982abb@qq.com");//true
checkMail("982abb@qq.com.cn");//true
checkMail("982abb@qq_.com_.cn");//false
// \\w{5,12}@\\w+(\\.[a-zA-Z]+)+
}
public static void checkMail(String mail){//检查邮件
System.out.println(mail.matches("\\w{6,12}@\\w+(\\.[a-zA-Z]+)+"));
/*
\\w代表出现的字符包括大小写字母和下划线_。\\w{6,12}代表大小写字母或者下划线出现的次数为6~12次。
\\w{6,12}@代表出现6~12此大小写字母后出现@字符。\\w+ 代表大小写字母或者下划线_出现的次数为1次或者1次以上。
\\.代表出现一个点. 。[a-zA-Z]+代表大小写字母出现一次或者多次。(\\.[a-zA-Z]+)+ 代表 .和[a-zA-Z]+出现一次或者一次以上
*/
}
}
网页爬虫
/*
模拟网页爬虫(蜘蛛)
获取一个文件中的邮箱
*/
import java.io.*;
import java.net.*;
import java.util.regex.*;
public class Demo {
public static void main(String[] args) throws Exception {
method2();
}
public static void method2() throws Exception {
URL url = new URL("file:///C:/Users/user/Desktop/web.html");
URLConnection conn = url.openConnection();
BufferedReader bufr = new BufferedReader(new InputStreamReader(
conn.getInputStream()));
String regex = "\\w+@\\w+(\\.\\w+)+";
Pattern p = Pattern.compile(regex); // 将规则封装成对象
String line = null;
while ((line = bufr.readLine()) != null) {
Matcher m = p.matcher(line);// 将正则表达式和字符串相关联,并返回一个匹配器引擎
while (m.find())
System.out.println(m.group());
}
}
public static void method1() throws Exception {
BufferedReader bufr = new BufferedReader(new FileReader("C:\\mail.txt"));
String regex = "\\w+@\\w+(\\.\\w+)+";
Pattern p = Pattern.compile(regex); // 将规则封装成对象
String line = null;
while ((line = bufr.readLine()) != null) {
Matcher m = p.matcher(line);// 将正则表达式和字符串相关联,并返回一个匹配器引擎
while (m.find())
System.out.println(m.group());
}
}
}