一、正则表达式:
就是符合一定规则的表达式。它是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。
作用:专门用来操作字符串的。
特点:用一些特定的符号来表示一些代码操作,这样就简化书写。所以学习正则表达式,就是在学习一些特殊符号的使用。
好处:可以简化对字符串的复杂操作。
弊端:符号定义越多,正则越长,阅读性越差。
二、常见正则表达式
说明:X表示字符X或者匹配的规则。
1、字符
x 字符 x
\\ 反斜线字符
\t 制表符 ('\u0009')
\n 新行(换行)符 ('\u000A')
\r 回车符 ('\u000D')
\f 换页符 ('\u000C')
\a 报警 (bell) 符 ('\u0007')
2、字符类
[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](减去)
3、预定义字符类
. 任何字符(与行结束符可能匹配也可能不匹配)
\d 数字:[0-9]
\D 非数字: [^0-9]
\s 空白字符:[ \t\n\x0B\f\r]
\S 非空白字符:[^\s]
\w 单词字符:[a-zA-Z_0-9]
\W 非单词字符:[^\w]
4、边界匹配器
^ 行的开头
$ 行的结尾
\b 单词边界
\B 非单词边界
\A 输入的开头
\G 上一个匹配的结尾
\Z 输入的结尾,仅用于最后的结束符(如果有的话)
\z 输入的结尾
三、具体操作功能:
1、匹配:String matches方法。用规则匹配整个字符串,只要有一处不符合规则,
就匹配失败。
2、切割:String split();
3、替换:String replaceAll();
[java] view plaincopy
- <span style="font-size:14px;">class RegexDemo
- {
- public static void main(String[] args)
- {
- //checkQQ();
- //demo();
- //checkTel();
- //splitDemo();
- replaceAllDemo();
- }
- public static void replaceAllDemo()
- {
- String str = "wer13844342432ty32131uirere24324ff";
- //将字符串中的数字替换成#。
- str = "erkktyqqquizzzzzo";//将叠词替换成$ ,//将重叠的字符替换成单个字母。zzzz->z
- String reg = "(\\d{4,})";
- reg = "(.)\\1+";
- String newStr="#";
- newStr = "$1";//取前面封装的第一个组。
- str = str.replaceAll(reg,newStr);
- System.out.println(str);
- }
- public static void splitDemo()
- {
- String str = "zhangsan.lisi.wangwu";
- str = "c:\\abc\\a.txt";
- str = "erkkyfaqqqfdzzzzsa";
- //String reg = " +";//按照多个空格来切割
- String reg = "\\.";//注意不能用单独的.或者\.来切,需要转义一下
- reg = "\\\\";
- reg = "(.)\\1+";//按照叠词完成切割。为了可以让规则的结果被重用
- //可以将规则封装成一个组,用()完成,组都有编号,
- //从1开始,想要使用已有的组可以通过\n来表示,n就是组的编号。
- String[] arr = str.split(reg);
- System.out.println(arr.length);
- for (String s : arr )
- {
- System.out.println(s);
- }
- }
- /*
- 匹配:手机号段只有 13xxx 15xxx 18xxx
- */
- public static void checkTel()
- {
- String tel ="17944445585";
- String telReg = "1[358]\\d{9}";
- System.out.println(tel.matches(telReg));
- }
- public static void demo()
- {
- String str = "bbg";
- String reg = "[bcd][a-z]";
- boolean b = str.matches(reg);
- System.out.println(b);
- }
- public static void checkQQ()
- {
- String qq = "98456465555";
- 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+"。。。。不合法");
- }
- /*
- 对QQ号码进行校验
- 要求:5~15位,0不能开头,只能是数字。
- 这种方式,使用了String类中的方法,进行组合完成了需求,但是代码过去繁琐。
- */
- public static void checkQQ_1()
- {
- String qq = "8s77777777";
- int len = qq.length();
- if (len>=5 && len<15)
- {
- if (!qq.startsWith("0")) //Ingeger.parseInt("12a");NumberFormatException
- {
- try
- {
- long l = Long.parseLong(qq);
- System.out.println("qq:"+l);
- }
- catch (NumberFormatException e)
- {
- System.out.println("出现非法字符。");
- }
- /*
- 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("长度错误");
- }
- }
- }</span>
四、正则表达式的第四个功能:
4、获取:将字符串中符合规则的子串取出。
操作步骤:
1、将正则表达式封装成对象
2、让正则对象和要操作的字符串相关联
3、关联后,获取正则匹配引擎。
4、通过引擎对符合规则的子串进行操作。比如取出。
[java] view plaincopy
- <span style="font-size:14px;">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 le ,da jia.";
- String reg = "\\b[a-z]{4}\\b";
- //将规则封装成对象。
- Pattern p = Pattern.compile(reg);
- //让正则对象和要作用的字符串相关联。获取匹配器对象。
- Matcher m = p.matcher(str);
- //System.out.println(m.matches());//其实String类中的matches 方法,
- //用的就是Pattern和Matcher对象来完成的,只不过被String的方法封装后,
- //用起来较为简单,但功能却单一。
- //boolean b = m.find();//将规则作用到字符串上,并进行符合规则的子串查找。
- //System.out.println(b);//用于获取匹配后的结果。
- System.out.println(m.matches());//这里匹配过一次,指针已经移动了,所以下面的操作是从新的指针位置开始的。
- while(m.find())//只有找了才能取
- {
- System.out.println(m.group());//用于获取匹配后的结果。
- System.out.println(m.start()+"...."+m.end());
- }
- }
- }</span>
练习操作
[java] view plaincopy
- <span style="font-size:14px;">import java.util.*;
- class RegexTest
- {
- public static void main(String[] args)
- {
- //test_1();
- //ipSort();
- checkMail();
- }
- /*
- 需求:对邮件地址进行校验。
- */
- public static void checkMail()
- {
- String mail = "abc12@sina.com.cn";
- String reg = "[a-zA-Z0-9_]+@[a-zA-Z0-9]+(\\.[a-zA-Z]+)+";//较为精确的匹配。
- reg = "\\w+@\\w+(\\.\\w+)+";//相对不太精确的匹配
- //mail.indexOf("@")!=-1;
- System.out.println(mail.matches(reg));
- }
- /*
- 需求:将下列字符串转成:我要学编程
- 到底用四种功能中的哪一个呢?或者哪几个呢?
- 思路方式:
- 1、如果只想知道该字符串是对是错,使用匹配
- 2、想要将已有的字符串变成另一个字符串,用替换
- 3、想要按照自定的方式将字符串变成多个字符串,用切割(获取规则之外的子串)
- 4、想要拿到符合需求的字符串子串,用获取。(获取符合规则的子串)
- */
- 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.013 10.10.10.10 2.2.2.2 8.109.90.30
- 将ip地址进行地址段顺序的排序。
- 还按照字符串的自然顺序,只要让他们的每一段都是3位即可
- 1、按照每一段需要的最多的0进行补齐,那么每一段就会至少保证有3位。
- 2、将每一段只保留3位,这样,所有的ip地址都是每一段3位
- */
- public static void ipSort()
- {
- String ip = "192.68.1.254 102.49.23.013 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");
- 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"));
- }
- }
- }</span>
五、正则表达式编程常用规则
1、上来不用说,先定义自己要操作的“字符串”和“正则规则”
String str=“我是一个字符串”;
String reg=“我是正则表达式”;
2、然后将正则规则封装成对象,使用的是(“pattern”样式的意思,“compile”编译的意思)
Pattern p=Pattern.compile(reg);
返回的是Pattern类型的数据
3、然后将“字符串“和”规则“进行关联
Matcher m=p.matcher(字符串);
4、使用while循环进行遍历,里面使用的是Matcher类创建的对象m调用自身方法find()返回的是boolean类型。
while(m.find()){
System.out.println(m.group()); //调用group方法返回的是满足条件的String类型的结果
}
六、网页爬虫
制作一个可以将一个网页或者指定文件中的全部的邮箱读取出来打印到控制台上。
[java] view plaincopy
- <span style="font-size:14px;">import java.io.*;
- import java.net.*;
- import java.util.regex.*;
- class RegexTest2
- {
- public static void main(String[] args) throws Exception
- {
- getMails_1();
- }
- public static void getMails_1() throws Exception
- {
- URL url = new URL("http://192.168.0.102:8080/myweb/mail.html");
- 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());
- }
- }
- }
- /*
- 获取指定文档中的邮件地址。
- 使用获取功能,Pattern Matcher
- */
- public static void getMails() throws Exception
- {
- 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());
- }
- }
- }
- }</span>