------- android培训、java培训、期待与您交流!----------
导读:正则表达式-特点、匹配、切割、替换,获取,网络编程-网页爬虫
1、正则表达式(特点、匹配、切割、替换)
- String包中的操作字符串的方法,操作起来,一、太简单,二、组合起来操作复杂数据代码过多。对于字符串进行操作即简单,又快捷的方式就是正则表达式。
- 正则表达式是用一堆符号来表示一堆代码。最终用的还是操作字符串的一些最常用的方法。Web技术中自定义的一些标签就是这样,这个标签就对应了一个Java类(用符号来代表一些代码的数据)。
- 正则表达式是java.util.regex中的类Pattern
/*
- 正则表达式:符合一定规则的表达式。
作用:用于专门操作字符串。
特点:用于一些特定的符号来表示一些代码操作。这样就简化书写。
所以学习正则表达式,就是在学习一些特殊符号的使用。
好处:可以简化对字符串的复杂操作。
弊端:符号定义越多,正则越长,阅读性越差。
- 具体操作功能:
1,匹配:booleanmatches(String regex)方法。用规则匹配整个字符串,只要有一处不符合规则,就匹配结束,返回false。(带有String regex的就是要匹配正则表达式。)
2,切割:Stringsplit();
3,替换:StringreplaceAll(regex,str);如果regex中有定义组,可以在第二参数中通过$符号获取正则表达式中的已有的组。
*/
- 组虽然作用起来比较简单,但是书写起来,阅读性极差。
在表达式 ((A)(B(C))) 中,存在四个这样的组:(看有几个左括号就封装成几个组)
1 ((A)(B(C)))
2 \A
3 (B(C))
4 (C)
- 当要替换复杂的字符串的时候,这个时候就要用到正则表达式。
- 在替换的过程中,我们可以通过另外的一个符号来获取前面规则中的一个组。如,用“$1”。表示前面规则中的第一个组。如果不写1发生字符串越界,因为他认为整个字符串就是一个组,即第0组。如果定义了一个()那么他就是从第1组开始编。
- class RegexDemo
{
publicstatic void main(String[] args)
{
//demo();
//System.out.println((char)11);
//checkTel();
//splitDemo("zhangsan.lisi.wangwu","\\."); //用点来分隔时的写法
//splitDemo("c:\\abc\\a.txt","\\\\"); //两个反斜杠的写法。
//splitDemo("erkktyqqquizzzzzo","(.)\\1+");
//按照叠词完成切割。为了可以让规则的结果被重用
//可以将规则封装成一个组。用()完成。组的出现都有编号。
//从1开始。 想要使用已有的组可以通过 \n(n就是组的编号)的形式来获取。
String str ="wer1389980000ty1234564uiod234345675f";//将字符串中的数组替换成#。
//replaceAllDemo(str,"\\d{5,}","#"); //数字如果超过5个的就把你替换为#
Stringstr1 = "erkktyqqquizzzzzo";//将叠词替换成$. //将重叠的字符替换成单个字母。zzzz->z
replaceAllDemo(str1,"(.)\\1+","$1");
}
publicstatic void replaceAllDemo(String str,String reg,String newStr)
{
str= str.replaceAll(reg,newStr);
System.out.println(str);
}
//正则表达式中有很多的符号,点就是一个特殊的符号,它代表任意字符。所以不能和点来直接的切东西。如果非要用点来切的话,可以转义一下。用“\\.”l因为在正则表达式中“\.”是一个整体,代表正则表达式中普通的一点。如果放在字符串中,还要把\给转义一下。
public static void splitDemo(String str,String reg)
{
//Stringreg = " +";//按照多个空格来进行切割(空格出现了一次或者多次)
String[]arr = str.split(reg);
System.out.println(arr.length);
for(Strings : arr)
{
System.out.println(s);
}
}
/*
匹配
手机号段只有 13xxx 15xxx 18xxxx
*/
publicstatic void checkTel()
{
Stringtel = "16900001111";
StringtelReg = "1[358]\\d{9}";
System.out.println(tel.matches(telReg));
}
publicstatic void demo()
{
Stringstr = "b23a23456789";
Stringreg = "[a-zA-Z]\\d*";
booleanb= str.matches(reg);
System.out.println(b);
}
publicstatic void checkQQ()
{
Stringqq = "123a454";
Stringregex = "[1-9]\\d{4,14}"; //等同于下面的语句。
//Stringregex = "[1-9][1-9]{4,14}"; //第一个字符中1到9中的一个,第二个字符是1到9中的一个,并且循环4到14次。
booleanflag = qq.matches(regex);
if(flag)
System.out.println(qq+"...isok");
else
System.out.println(qq+"...不合法");
}
/*
对QQ号码进行校验
要求:5~15 0不能开头,只能是数字
这种方式,使用了String类中的方法,进行组合完成了需求。但是代码过于复杂。
*/
publicstatic void checkQQ_1()
{
Stringqq = "1882345a0";
intlen = qq.length();
if(len>=5&& len<=15)
{
if(!qq.startsWith("0"))//Integer.parseInt("12a");NumberFormatException
{
try
{
longl = Long.parseLong(qq);
//可以用parseInt来判断是否有非法的,位数最多有15位因此,可以用parseLong();
System.out.println("qq:"+l);
}
catch(NumberFormatException e)
{
System.out.println("出现非法字符.......");
}
/*
char[]arr = qq.toCharArray();//123a4
booleanflag = true;
for(intx=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("长度错误");
}
}
}
- 部分常用正则表达式
Ø 字符
x 字符 x
\\ 反斜线字符
\0n 带有八进制值 0 的字符 n (0 <= n <= 7)
\0nn 带有八进制值 0 的字符 nn (0 <= n <= 7)
\0mnn 带有八进制值 0 的字符 mnn(0 <= m <= 3、0 <= n <= 7)
\xhh 带有十六进制值 0x 的字符 hh
\uhhhh 带有十六进制值 0x 的字符 hhhh
\t 制表符('\u0009')
\n 新行(换行)符('\u000A')
\r 回车符('\u000D')
\f 换页符('\u000C')
\a 报警 (bell) 符 ('\u0007')
\e 转义符('\u001B')
\cx 对应于 x 的控制符
Ø 字符类
[abc] a、b 或 c(简单类)(可以用来判断字符串中某一个字符位上出现的字符,要么是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,在编程的时候要写为\\d)
\D 非数字: [^0-9]
\s 空白字符:[\t\n\x0B\f\r]
\S 非空白字符:[^\s]
\w 单词字符:[a-zA-Z_0-9] (起邮箱名,字母数字划线)
\W 非单词字符:[^\w]
Ø Greedy 数量词
X? X,一次或一次也没有
X* X,零次或多次
X+ X,一次或多次
X{n} X,恰好 n 次
X{n,} X,至少 n 次
X{n,m} X,至少 n 次,但是不超过 m 次
Ø 边界匹配器
^ 行的开头
$ 行的结尾
\b 单词边界
\B 非单词边界
\A 输入的开头
\G 上一个匹配的结尾
\Z 输入的结尾,仅用于最后的结束符(如果有的话)
\z 输入的结尾
2、正则表达式(获取)
- 匹配、切割、替换这三个只能按照规则操作一些字符串,而我现在想把符合规则的子串取出来。以前取子串用subString来取,如果想取描写位置的字符串的话,可以用indexOf()来取。
/*
- 正则表达式的第四个功能。
4,获取:将字符串中的符合规则的子串取出。
Ø 操作步骤:
1,将正则表达式封装成对象。
2,让正则对象和要操作的字符串相关联。
3,关联后,获取正则匹配引擎。
4,通过引擎对符合规则的子串进行操作,比如取出。
*/
- java.util.regex中的类Pattern,正则表达式的编译表示形式。这个类没有构造方法,不能new对象,所以它中的方法都是静态的方法(无对象持有的特有数据),返回的是静态的对象。
- 方法:
Ø static Pattern compile(String regex):将给定的正则表达式编译到模式中。(将正则传进来,返回一个Pattern的对象)
Ø Matcher matcher(CharSequence input):创建匹配给定输入与此模式的匹配器。(返回此模式的新匹配器)
- java.util.regex中的类Matcher,可以通过解释Pattern 对 character sequence 执行匹配操作的引擎。(我们称之为匹配器,或者称之为引擎)
- 方法:
Ø boolean matches():尝试将整个区域与模式匹配。(String对象中的matcher(),就是通过Pattern和Matcher两个对象来完成的。)
Ø String replaceAll(String replacement):替换模式与给定替换字符串相匹配的输入序列的每个子序列。(String类中的String replaceAll(Stringreplacement),用的就是它)
Ø boolean find():尝试查找与该模式匹配的输入序列的下一个子序列。(从现在指针的位置身后查找)
Ø String group():返回由以前匹配操作所匹配的输入子序列。(获取匹配后的结果)
Ø int start():返回以前匹配的初始索引。
Ø lnt end():返回最后匹配字符之后的偏移量。
- import java.util.regex.*;
class RegexDemo2
{
publicstatic void main(String[] args)
{
getDemo();
}
publicstatic void getDemo()
{
Stringstr = "ming tian jiu yao fang jia le ,da jia。";
System.out.println(str);
String reg = "\\b[a-z]{4}\\b"; //找到三个字母后,还要进行单词的匹配“\b”
//将规则封装成对象。
Patternp = Pattern.compile(reg);
//让正则对象和要作用的字符串相关联。获取匹配器对象。
Matcherm = p.matcher(str);
//System.out.println(m.matches());
//其实String类中的matches方法。用的就是Pattern和Matcher对象来完成的。只不过被String的方法封装后,用起来较为简单。但是功能却单一。
//booleanb = m.find();//将规则作用到字符串上,并进行符合规则的子串查找。
//System.out.println(b);
//System.out.println(m.group());//用于获取匹配后结果。
//System.out.println("matches:"+m.matches()); //一个匹配器,对于对于应一个指针。如果这里进行匹配,则将整个的str和规则进行匹配,返回的是false,这个时候指针还要向下走,接着循环的匹配。
while(m.find()) //(取出方式用这个来完成)类似于迭代器,用循环。你只有去找,去匹配了才能去取。你不找,不把规则作用在字符串上,你是找不了的。
{
System.out.println(m.group());
System.out.println(m.start()+"...."+m.end());//获取子串的索引位置(含对不含尾)
}
}
}
3、练习
- import java.util.*;
class RegexTest
{
publicstatic void main(String[] args)
{
// test_1();
// ipSort();
checkMail();
}
/*
需求:对邮件地址进行校验。
*/
publicstatic void checkMail()
{
Stringmail = "abc12@sina.com";
mail= "1@1.1";
Stringreg = "[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,想要拿到符合需求的字符串子串,获取。获取符合规则的子串。
*/
publicstatic void test_1()
{
Stringstr = "我我...我我...我要..要要...要要...学学学....学学...编编编...编程..程.程程...程...程";
/*
将已有字符串变成另一个字符串。使用 替换功能。
1,可以先将 . 去掉。
2,在将多个重复的内容变成单个内容。
*/
str =str.replaceAll("\\.+","");
System.out.println(str);
str= str.replaceAll("(.)\\1+","$1");
System.out.println(str);
}
/*
192.68.1.254102.49.23.013 10.10.10.10 2.2.2.2 8.109.90.30
将ip地址进行地址段顺序的排序。
还按照字符串自然顺序,只要让它们每一段都是3位即可。
1,按照每一段需要的最多的0进行补齐,那么每一段就会至少保证有3位。
2,将每一段只保留3位。这样,所有的ip地址都是每一段3位。
*/
publicstatic void ipSort()
{
Stringip = "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"); //每一个段至少是一位。将每一个段补最多的2个0;
System.out.println(ip);
ip= ip.replaceAll("0*(\\d{3})","$1"); //获取每段中,补0后的后三位
System.out.println(ip);
String[]arr = ip.split(" ");
TreeSet<String>ts = new TreeSet<String>();
for(Strings : arr)
{
ts.add(s);
}
for(Strings : ts)
{
System.out.println(s.replaceAll("0*(\\d+)","$1")); //将补的0省去不写。
}
}
}
- 想注册我的论坛,到邮箱里去点激活链接去,你要是地址写错了,邮件就发错了,你收不到邮件,我的论坛你就登不上去,确保会员邮箱是正确的,因为我要给他发一些广告。
3、网络编程(网页爬虫)
/*
网页爬虫(蜘蛛)
*/
import java.io.*;
import java.util.regex.*;
import java.net.*;
import java.util.*;
class RegexTest2
{
publicstatic void main(String[] args) throws Exception
{
getMails_1();
}
publicstatic void getMails_1()throws Exception
{
URLurl = new URL("http://192.168.1.254:8080/myweb/mail.html");
URLConnectionconn = url.openConnection();
BufferedReaderbufIn = new BufferedReader(new InputStreamReader(conn.getInputStream()));
Stringline = null;
Stringmailreg = "\\w+@\\w+(\\.\\w+)+";
Patternp = Pattern.compile(mailreg);
while((line=bufIn.readLine())!=null)
{
Matcherm = p.matcher(line);
while(m.find())
{
System.out.println(m.group());
}
}
}
/*
获取指定文档中的邮件地址。
使用获取功能。Pattern Matcher
*/
publicstatic void getMails()throws Exception
{
BufferedReaderbufr =
newBufferedReader(new FileReader("mail.txt"));
Stringline = null;
Stringmailreg = "\\w+@\\w+(\\.\\w+)+";
Patternp = Pattern.compile(mailreg);
while((line=bufr.readLine())!=null)
{
Matcherm = p.matcher(line);
while(m.find())
{
System.out.println(m.group());
}
}
}
}
- 早期的时候是算邮箱,用随机的方式或者用顺序的方式产生,计数器。写邮件程序,往这一批邮箱里面发指定的广告页面。但是这一批邮箱里面可能只有几个是注册过的,剩下有很多都是没有注册过的。中奖率不高。那么从互联网上获取一批已经存在的邮件不就可以了吗。怎么获取?搞一个爬虫过去,把网页获取到了之后,把这里面的数据一行一行的去扫,把凡是符合邮箱的规则的一段数据,全取过来。
- 百度的程序都是自动的,散发出n个蜘蛛在互联网上开始爬,把最新的网页博客都爬过来,只要爬完了之后,你只要搜都能搜到,都在百度的服务器上呢。现在还爬关键字。以前爬网头的关键字,现在还爬网页主体数据的关键字。
- 在以后学JavaWeb的时候会学到一个JavaMail,用java来写一个邮件收发程序。完全可以用你写的程序给新浪,搜狐发邮件。自己写一个邮件服务器,再把邮件地址读出来以后,发垃圾邮件就OK了。
------- android培训、java培训、期待与您交流!----------