转载请声明出处:http://blog.csdn.net/zhongkelee/article/details/47708405
简述
正则表达式,字面意思就是正确的规则,它是专门用于操作字符串的规则。
好处:规则是由符号组成的。正则的出现,使字符串的复杂操作变得更为简单。
特点:将对字符串操作的代码用一些符号来表示。只要使用了指定符号,就可以调用底层的代码对字符串进行操作。符号的出现,简化了代码的书写。
弊端:符号的出现虽然简化了书写,但是却降低了阅读性。
其实更多是用正则解决字符串操作的问题。所以学习正则其实就是学习符号的使用。
示例:练习校验QQ号的传统方式和正则表达式方式。
package ustc.lichunchun.regex;
public class RegexDemo {
public static void main(String[] args) {
/*
* 正则表达式:正确的规则。专门用于对字符串的操作。
* 好处:规则是由符号组成的。正则的出现,使字符串的复杂操作变得更为简单。
* 特点:将对字符串操作的代码用一些符号来表示。只要使用了指定符号,就可以调用底层的代码对字符串进行操作。
* 符号的出现,简化了代码的书写。
* 弊端:符号的出现虽然简化了书写,但是却降低了阅读性。
* 其实更多是用正则解决字符串操作的问题。
* 所以学习正则其实就是学习符号的使用。
*/
String QQ = "0124763";
boolean b = checkQQ(QQ);
if(b){
System.out.println(QQ+" is ok");
}else{
System.out.println(QQ+" is nonono");
}
System.out.println("-------------------");
boolean b1 = QQ.matches("[1-9][0-9]{4,14}");
System.out.println(QQ+": "+b1);
System.out.println("-------------------");
String temp = "aaaaa2";
boolean res = temp.matches("a{5}\\d");
System.out.println(temp+":"+res);
}
/*
* 校验QQ号。5~15位 只能是数字,0不能开头。
*/
public static boolean checkQQ(String QQ){
boolean flag = false;
int len = QQ.length();
if(len>=5 && len<=15){
if(!QQ.startsWith("0")){//或者charAt()
try{
long qq_num = Long.parseLong(QQ);
flag = true;
System.out.println("QQ:"+qq_num);
}catch(NumberFormatException e){
System.out.println("非法QQ号");
}
}else{
System.out.println("不能0开头");
}
}else{
System.out.println("长度错误");
}
return flag;
}
}
常见操作
下面重点介绍一下正则表达式对字符串的常见操作。具体可以分为匹配、分割、替换、获取这四大操作。这其中,前三个操作都是用的是java.lang.String类的成员方法,即match、split、replaceAll方法,但它们底层都是用正则对象实现的。
1.匹配
String类中提供了匹配 boolean matches(regex) 的方法。
String reg = "[1—9][0—9]{4,14}";
boolean b = qq.matches(reg); //将正则和字符串关联对字符串进行匹配。
2.切割
String类中提供了 String[] split(regex) 的方法。
3.替换
String类中提供了String replaceAll(regex, replacement)的方法。
4.获取
最后一个获取功能,String类没有给我们提供相应的方法,这里我们需要借助于另外两个对象:
正则模式对象:java.util.regex.Pattern --> 封装正则
匹配器对象:java.util.regex.Matcher --> 关联字符串
具体来说:
(1)先要将正则表达式编译成正则对象。使用的是Pattern中静态方法 compile(regex);
(2)通过Pattern对象获取Matcher对象。Pattern用于描述正则表达式,可以对正则表达式进行解析。
而将规则操作字符串,需要从新封装到匹配器对象Matcher中。
然后使用Matcher对象的方法来操作字符串。如何获取匹配器对象呢?
通过Pattern对象中的matcher方法。该方法可以正则规则和字符串想关联。并返回匹配器对象。
(3)使用Matcher对象中的方法即可对字符串进行各种正则操作。
package ustc.lichunchun.regex;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegexTest {
public static void main(String[] args) {
/*
* 演示正则表达式对字符串的常见操作。
*
* String类中的match、split、replaceAll方法,底层都是用正则对象实现的。
*
* 1.匹配
* String类中提供了匹配boolean matches(regex)的方法。
*
* 2.切割
* String类中提供了String[] split(regex)的方法。
*
* 3.替换
* String类中提供了String replaceAll(regex, replacement)的方法。
*
* 4.获取
* 正则模式对象:java.util.regex.Pattern-->封装正则
* 匹配器对象:java.util.regex.Matcher-->关联字符串
*/
//matchesDemo();//匹配
//splitDemo();//分割
//replaceDemo();//替换
getDemo();//获取
}
public static void matchesDemo() {
//需求:校验手机号码是否正确。
String tel = "15855159331";
String regex = "1[358]\\d{9}";
boolean b = tel.matches(regex);
System.out.println(tel+":"+b);
}
public static void splitDemo() {
String temp = "zhangsan lisi wangwu";
String regex = " +";
String temp1 = "zhangsan.lisi.wangwu";
String regex1 = "\\.";//正则会将'.'解析为特定含义,代表任意字符,
//但是我们这里需要的就是'.'特定字符,所以用转义字符'\.'和转义字符'\\'。
String temp2 = "qwe##rty$$$$tyuvvvvvvvio";
String regex2 = "(.)\\1+";//为了实现规则的复用,用()将需要复用的规则封装,
//就称为正则表达式中的"组",每一个组都有一个编号,从1开始。(组零始终代表整个表达式)
//通过使用编号就可以复用对应组的规则内容。(编号也必须使用\\转义)
//注意:编号必须用在组的后面。也就是说:先封装完规则再用角标调用。
// ((A)(B(C))) 共四组,有几个左括号,就有几组。最左边的左括号封装的是第1组,以此类推。
String[] names = temp2.split(regex2);
for (String name : names) {
System.out.println("-"+name+"-");
}
}
public static void replaceDemo() {
String temp = "15855159331";
temp = temp.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2");
//在一个字符串规则中,用'\编号'的形式就可以取组了。
//$可以在多参数时,后面的参数可以通过'$编号'的形式取到前一个参数的组。
String temp1 = "qwe##rty$$$$tyuvvvvvvvio";
temp1 = temp1.replaceAll("(.)\\1+", "$1");
System.out.println(temp1);
}
public static void getDemo() {
/*
* 实现获取:将符合规则的内容取出来,用到正则表达式对象。java.utilregex.Pattern
*
* 思路:
* 1.将字符串规则封装成Pattern对象。Pattern compile(regex);
* 2.通过正则模式对象Pattern获取匹配器对象Matcher。用于将正则规则作用到要操作的字符串上。Matcher matcher(input);
* 3.通过匹配器对象的方法,对字符串进行操作。
*
* Pattern p = Pattern.compile("a*b");//将规则编译成对象。
* Matcher m = p.matcher("aaaaab");//和要操作的字符串关联,生成匹配器对象。
* boolean b = m.matches();//使用匹配器对象的方法对字符串进行操作。
*/
//需求:获取字符串中符合规则的内容。
String temp = "da jia zhu yi le,ming tina fang jia le!";
System.out.println(temp);
//取出由三个字母组成的单词,注意单词边界。
String regex = "\\b[a-zA-Z]{3}\\b";
//1.将规则编译成Pattern对象。
Pattern p = Pattern.compile(regex);
//2.和字符串关联,获取匹配器对象。
Matcher m = p.matcher(temp);
while(m.find()){
System.out.println(m.start()+":"+m.group()+":"+m.end());//根据start和end,getSubString.
}
/*
da jia zhu yi le,ming tina fag jia le!
3:jia:6
7:zhu:10
32:jia:35
*/
}
}
练习1:将"我我....我我我....我要....要...要要....要要..学学学...学学编...编编..编编程程....程..程程" 还原成:我要学编程。
练习2:对ip地址进行排序:"192.168.1.200 17.10.10.10 3.3.50.3 127.0.0.1"。
练习3:校验邮件地址。
package ustc.lichunchun.regex;
import java.util.Arrays;
public class YourRegexTest {
public static void main(String[] args) {
//test_1();
//test_2();
checkMail();
}
/*
* 练习1:
* "我我....我我我....我要....要...要要....要要..学学学...学学编...编编..编编程程....程..程程"
* 还原成:我要学编程。
*/
public static void test_1() {
String temp = "我我....我我我....我要....要...要要....要要..学学学...学学编...编编..编编程程....程..程程";
//1.明确要使用替换。replaceAll(regex, String)
//2.将点先干掉
temp = temp.replaceAll("\\.+", "");
//3.将叠词干掉
temp = temp.replaceAll("(.)\\1+", "$1");
System.out.println(temp);
}
/*
* 练习2:对ip地址进行排序。
* 192.168.1.200 17.10.10.10 3.3.50.3 127.0.0.1
*/
public static void test_2(){
String temp = "192.168.1.200 17.10.10.10 3.3.50.3 127.0.0.1";
//String[] ips = temp.split(" +");
//Arrays.sort(ips);//这是按照字符串字典顺序排的,不符合需求。
/*
问题在哪儿呢?是因为每一个地址段的位数不对。
如果位数都是三位就可以了。只有补0了。
每一段位数都不同,咋补?
干脆按照最大所需0的个数补齐。每一段都补两个0。但最终我们只截取每段的最后三位。
*/
//补两个0,连续数字。
temp = temp.replaceAll("(\\d+)", "00$1");
//保留每段最后3位
temp = temp.replaceAll("0*(\\d{3})", "$1");
//排序
String[] ips = temp.split(" +");
Arrays.sort(ips);
//或者:
//TreeSet<String> ts = new TreeSet<String>();
//ts.add(ip);
for(String ip : ips){
System.out.println(ip.replaceAll("0*(\\d+)", "$1"));
}
}
/*
* 练习3:校验邮件地址。
*/
public static void checkMail(){
String mail = "abc12@sina.com.cn";
String regex = "\\w+@[a-zA-Z0-9]+(\\.[a-zA-Z]{2,3}){1,3}";
regex = "\\w+@\\w+(\\.\\w+)+";//笼统方式,1@1.1都行。
boolean b = mail.matches(regex);
System.out.println(mail+":"+b);
}
}
练习4:去除一串数字中连续相同的3个数字,如1122333224455546667,变成1127。(华为2016机试题)
package huawei.job;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Main33 {
public static void main(String[] args) {
String line = "1122333224455546667";
while(isRepeatNum(line)){
line = line.replaceAll("(\\d)\\1{2}", "");
}
System.out.println(line);
}
public static boolean isRepeatNum(String str){
Matcher m = Pattern.compile("(\\d)\\1{2}").matcher(str);
//-- \\d已经算一个数字,后面\\1{2}是接着这个数字后的相同两个数字
if(m.find()){
return true;
}
return false;
}
}
爬虫
网络爬虫:其实就是一个程序用于在互联网中获取符合制定规则的数据。
示例:爬取文件中的邮箱地址。
package ustc.lichunchun.netspider;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class NetSpider {
public static void main(String[] args) throws IOException {
/*
* 网络爬虫:其实就是一个程序用于在互联网中获取符合制定规则的数据。
*
* 爬取邮箱地址。
*/
//1.将文件封装成File对象。
File file = new File("mail.htm");
String regex = "\\w+@\\w+(\\.\\w+)+";
List<String> mailList = getMails(file, regex);
for(String mail:mailList){
System.out.println(mail);
}
}
public static List<String> getMails(File file, String regex) throws IOException {
//1.读取数据。
BufferedReader bufr = new BufferedReader(new FileReader(file));
//2.将正则封装成对象。
Pattern p = Pattern.compile(regex);
//3.定义List集合。
List<String> list = new ArrayList<String>();
String line = null;
while((line = bufr.readLine())!=null){
//4.对读取的数据进行规则的匹配,从中获取符合规则的数据。
Matcher m = p.matcher(line);
while(m.find()){
//5.将符合规则的数据存储到集合中。
list.add(m.group());
}
}
return list;
}
}
练习:网页爬虫。(其实就是利用网络通信和URL技术,后一篇博客会详细介绍JavaSE网络编程)
参考代码后续会补上~~~
转载请声明出处:http://blog.csdn.net/zhongkelee/article/details/47708405