黑马程序员 java_正则表达式笔记

来源:互联网 发布:短发发型设计软件 编辑:程序博客网 时间:2024/06/15 01:08

-------android培训 、java培训、期待与您交流! ----------

正则表达式

 在编写处理祖父穿的程序或者网页时,经常会有查找符合某些复杂规则的字符串的需要,正则表达式就是用于描述这些规则的工具,即是记录文本规则的代码。

作用用于专门操作字符串  是操作字符串的规则.

 特点 用一些特定的符号来表示一些代码操作,这样就简化了书写  所以学习正则表达式就是在学习一些特殊符号的使用.

 好处 可以简化对字符串的复杂操作.

 弊端  符号定义越多正则越长 阅读性越差.


\ba\w*\b匹配以字母a开头的单词——先是某个单词开始处(\b),然后是字母a,然后是任意数量的字母或数字(\w*),最后是单词结束处(\b)。

\d+匹配1个或更多连续的数字。这里的+是和*类似的元字符,不同的是*匹配重复任意次(可能是0次),而+则匹配重复1次或更多次

\b\w{6}\b 匹配刚好6个字符的单词

元字符^(和数字6在同一个键位上的符号)和$都匹配一个位置,这和\b有点类似。^匹配你要用来查找的字符串的开头,$匹配结尾。这两个代码在验证输入的内容时非常有用,比如一个网站如果要求你填写的QQ号必须为5位到12位数字时,可以使用:^\d{5,12}$

这里的{5,12}和前面介绍过的{2}是类似的,只不过{2}匹配只能不多不少重复2次{5,12}则是重复的次数不能少于5次,不能多于12次,否则都不匹配。

因为使用了^$,所以输入的整个字符串都要用来和\d{5,12}来匹配,也就是说整个输入必须是5到12个数字,因此如果输入的QQ号能匹配这个正则表达式的话,那就符合要求了。

采用上面的方法,只能保证在该字符串中包含5 到12个数字。

同样是QQ号匹配还可以用另外一种方式 [1-9]\\d{4,14} [1-9]表示第一位只能是1-9中的一个数字,\\d{4,14}表示接下来是4-14为数字

public static void checkQQ(){String qq="1232434534";String regex = "[1-9]\\d{4,14}";boolean flag =qq.matches(regex);if(flag)sop(qq+"-----ok--");elsesop(qq+"--no-no-");}public static void checkQQ_2(){String qq= "123qq45678";String regex = "[1-9][0-9]{4,14}";boolean flag =qq.matches(regex);if(flag)sop(qq+"-----ok--");elsesop(qq+"--no-no-");}

和忽略大小写的选项类似,有些正则表达式处理工具还有一个处理多行的选项。如果选中了这个选项,^$的意义就变成了匹配行的开始处和结束处

[aeiou]就匹配任何一个英文元音字母[.?!]匹配标点符号(.或?或!)

我们也可以轻松地指定一个字符范围,像[0-9]代表的含意与\d就是完全一致的:一位数字;同理[a-z0-9A-Z_]也完全等同于\w(如果只考虑英文的话)。

下面是一个更复杂的表达式:\(?0\d{2}[)-]?\d{8}

这个表达式可以匹配几种格式的电话号码,像(010)88886666,或022-22334455,或02912345678等。我们对它进行一些分析吧:首先是一个转义字符\(,它能出现0次或1次(?),然后是一个0,后面跟着2个数字(\d{2}),然后是)-空格中的一个,它出现1次或不出现(?),最后是8个数字(\d{8})。

分枝条件

不幸的是,刚才那个表达式也能匹配010)12345678(022-87654321这样的“不正确”的格式。要解决这个问题,我们需要用到分枝条件。正则表达式里的分枝条件指的是有几种规则,如果满足其中任意一种规则都应该当成匹配,具体方法是用|把不同的规则分隔开。听不明白?没关系,看例子:

0\d{2}-\d{8}|0\d{3}-\d{7}这个表达式能匹配两种以连字号分隔的电话号码:一种是三位区号,8位本地号(如010-12345678),一种是4位区号,7位本地号(0376-2233445)

\(0\d{2}\)[- ]?\d{8}|0\d{2}[-]?\d{8}这个表达式匹配3位区号的电话号码,其中区号可以用小括号括起来,也可以不用,区号与本地号间可以用连字号或空格间隔,也可以没有间隔。你可以试试用分枝条件把这个表达式扩展成也支持4位区号的。

\d{5}-\d{4}|\d{5}这个表达式用于匹配美国的邮政编码。美国邮编的规则是5位数字,或者用连字号间隔的9位数字。之所以要给出这个例子是因为它能说明一个问题:使用分枝条件时,要注意各个条件的顺序。如果你把它改成\d{5}|\d{5}-\d{4}的话,那么就只会匹配5位的邮编(以及9位邮编的前5位)。原因是匹配分枝条件时,将会从左到右地测试每个条件,如果满足了某个分枝的话,就不会去再管其它的条件了。

分组

我们已经提到了怎么重复单个字符(直接在字符后面加上限定符就行了);但如果想要重复多个字符又该怎么办?你可以用小括号来指定子表达式(也叫做分组),然后你就可以指定这个子表达式的重复次数了,你也可以对子表达式进行其它一些操作(后面会有介绍)。

(\d{1,3}\.){3}\d{1,3}是一个简单的IP地址匹配表达式。要理解这个表达式,请按下列顺序分析它:\d{1,3}匹配1到3位的数字(\d{1,3}\.){3}匹配三位数字加上一个英文句号(这个整体也就是这个分组)重复3次,最后再加上一个一到三位的数字(\d{1,3})。

不幸的是,它也将匹配256.300.888.999这种不可能存在的IP地址。如果能使用算术比较的话,或许能简单地解决这个问题,但是正则表达式中并不提供关于数学的任何功能,所以只能使用冗长的分组,选择,字符类来描述一个正确的IP地址:((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)

 

需求将下列字符串转成 我要学编程 


我我...我我...我要..要要..要要..学学学..学学..编编编..编程.程程...程..程
分析 到底用四种功能中的哪一个呢,或者哪几个
思路 
1 如果只想知道该字符串是对是错,使用匹配 
2 想要将已有的字符串变成另一个字符串,替换
3 想要按照指定的方式将字符串变成多个字符串, 切割 获取规则以外的子串
4 想要拿到符合需求的字符串子串  获取 获取符合规则的子串


需求2 
一堆地址 
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位。

class RegexTest {public static void sop(Object obj){System.out.println(obj);}public static void main(String[] args) { //test_1();// ipSort();checkMail();}public static void test_1(){String str = "我我...我我...我要..要要..要要..学学学..学学..编编编..编程.程程...程..程";/*将已有字符串编程另一个字符串 使用替换功能1 可以先将 .去掉2 再将多个重复的内容编程单个内容 */str = str.replaceAll("\\.+",""); //一个以上的点替换成空字符串 干掉点sop(str);str = str.replaceAll("(.)\\1+","$1"); //用组 把叠词干掉sop(str);}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";// \\d+ 一连串数字  被重用 装组 (\\d+)  00$1 第一位前面补俩0 ip = ip.replaceAll("(\\d+)","00$1");sop(ip);// 0*(\\d{3}) 0 没有或多次共连续3个数ip = ip.replaceAll("0*(\\d{3})","$1");sop(ip);String[] arr = ip.split(" +");TreeSet<String> ts = new TreeSet<String>();for(String s : arr){ts.add(s);}for(String s : ts){sop(s.replaceAll("0*(\\d+)","$1")); //去0 输出}}/*需求 对邮件地址进行校验 */public static void checkMail(){String mail = "sad2323@163.com.cn";//较为精确的匹配String reg = "[a-zA-Z0-9_]{6,12}@[a-zA-Z0-9]+(\\.[a-zA-Z]+){1,3}"; reg = "\\w+@\\w+(\\.\\w+)+"; //相对不太精确的匹配sop(mail.matches(reg));}}

正则表达式的第四个功能
4 获取 将字符串中符合规则的子串取出 
操作步骤 
1 先将正则表达式封装成对象,
2 让正则对象和 要操作的字符串想关联
3 关联后 获取正则匹配引擎
4 通过引擎对符合规则的子串进行操作,比如取出

import java.util.regex.*;class RegexDemo2{public static void sop(Object obj){System.out.println(obj);}public static void main(String[] args) {getDemo();}public static void getDemo(){String str = "ming tian ju yao fang jia le da jia";//str="136546543";//String reg = "[1-9]\\d{4,14}";String reg = "\\b[a-z]{3}\\b"; // \b 单词结束标记//将规则封装成对象Pattern p = Pattern.compile(reg);//让正则对象和要作用的字符串相关联。 获取匹配器对象Matcher m = p.matcher(str);//sop(m.matches());//其实String类中的matches方法,用的就是Pattern和Matcher对象来完成的//只不过被String的方法封装后,用起来较为简单 但功能却单一 //boolean b = m.find();//将规则作用在字符串上,并进行符合规则的子串查找//sop(b);while (m.find()){sop(m.group());//用于获取匹配后的结果}}}
class  RegexDemo{public static void sop(Object obj){System.out.println(obj);}public static void main(String[] args) {网页爬虫(蜘蛛) splitDemo("sdaddftterrgcf","(.)\\1+"); //按照叠词完成切割 叠词 后一个跟前一个是一致的/*怎么表示后一个跟前一个一样呢   . 表示任意字符    把要重用的部分()起来 形成一个重用组这个结果就 这个组封装后悔有一个编号    从1开始 想要使用已有的组可以通过\n的形式获取 n就是租的编号   (.)\\1; 表示第一位的内容在第二位又出现了   (.)\\1+; 切多个一样的((())())  有几个左括号就有几组 这个是由四组第一个左括号是第一次 2是2 3是3 4是4*/}public static void splitDemo(String str,String reg){    //String reg = " +";//空格符出现了一次或多次 按多个空格来进行切割 String[] arr = str.split(reg);sop(arr.length);for(String s : arr){sop(s);}}public static void demo(){String str = "as";//String reg = "[bcd]";//这个字符串中的第一个字符只能是b,c或者d 字符串只能有一个字符//String reg = "[bcd][a-z]";// 第一个字符同上 第二个字符只能是小写字母String reg = "[a-zA-Z]\\d?";//第一位是个字母 第二位是个数字有可能出现也有可能不出现要么有一个要么没有//?变成* 表示后面有0个数字或多个boolean  b=str.matches(reg);sop(b);}
网页爬虫(蜘蛛) 获取网页上的email

import java.io.*;import java.util.regex.*;import java.net.*;class  RegexTest2{public static void main(String[] args) throws Exception{getMails();}public static void sop(Object obj){System.out.println(obj);}/*获取指定文档中的邮件地址使用获取功能 Pattern Matcher*///爬网页的public static void getMails()throws Exception{URL url = new URL("http://tieba.baidu.com/p/2219661488");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()){//找一次取一次sop(m.group());}}}//爬文件的public static void getMails_1()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()){//找一次取一次sop(m.group());}}}}

【参考文献】

http://www.cnblogs.com/deerchao/archive/2006/08/24/zhengzhe30fengzhongjiaocheng.html

-------android培训 、java培训、期待与您交流! ----------
原创粉丝点击