黑马程序员--正则表达式(regex)

本文介绍了正则表达式的概念及应用,包括匹配、切割、替换和获取等核心功能,并通过实例展示了如何使用正则表达式解决实际问题。

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

一、引入正则表达式

可以证明:编程中最常见的操作莫过于对字符串的操作,既然对于字符串的操作这么频繁,那么就应该有相应的工具来操作它,正则表达式( RegularExpression )正好解决了这个问题。
在计算机科学中,是指一个用来描述或者匹配一系列符合某个句法规则的字符串的单个字符串。在很多文本编辑器或其他工具里,正则表达式通常被用来检索和/或替换那些符合某个模式的文本内容。许多程序设计语言都支持利用正则表达式进行字符串操作。 
简单地说:
正则表达式:符合一定规则的表达式。
作用:用于专门操作字符串,可以用于模式匹配和替换的强有力的工具。
特点:用于一些特定的符号来表示一些代码操作。这样就简化书写,提高效率。
所以学习正则表达式,就是在学习一些特殊符号的使用。
好处:可以简化对字符串的复杂操作。
弊端:符号定义越多,正则越长,阅读性越差。
具体有四个功能:
1,匹配:String  matches方法。用规则匹配整个字符串,只要有一处不符合规则,就匹配结束,返回false
2,切割:String split();
3,替换:String replaceAll(regex,str);如果regex中有定义组,可以在第二参数中通过$符号获取正则表达式中的已有的组。
4,获取:将字符串中的符合规则的子串取出。

二、规则:

    字符                                    字符类

X 字符X [abc] a,bc(简单类)

\\ 反斜线字符 [^abc] 除了abc的任何字符

\0n 八进制的字符n [a-zA-Z] az,或AZ(范围)

\t 制表符 [a-d[m-p]] 含义与[a-dm-p]相同(并集)

\n 换行符 [a-z&&[def]] 结果与[def]相同但表现不同(交集)

\r 回车符 [a-z&&[^def]] a-z中除去def的字符(交集) \f 换页符 [a-z&&[^a-d]] a-z中除去a-d的字符(交集)

\a 报警 预定义字符类

. 任意字符(与行结束符可能匹配也可能不匹配)

\d 数字类:[0-9] \D 非数字类:[^0-9]

\w 单词字符:[a-zA-Z_0-9]

\W 非单词字符:[^\w]

\s 空白字符[\t\n\r\f\x0B]

\S 非空白字符 [^\s] 边界匹配器

^ 行的开头
$行的结尾
\b单词边界
\B非单词边界
\A输入的开头
\G上一个匹配的结尾
\Z输入的结尾,仅用于最后的结束符(如果有的话)
\z输入的结尾

Greedy 数量词

X X,一次或一次也没有

X* X,零次或多次

X+ X,一次或多次

X{n} X,恰好n

X{n,} X,至少n

X{n,m} X,至少n次,但不超过m

组和捕获

捕获组可以通过从左到右计算其开括号来编号。例如,在表达式 ((A)(B(C))) 中,存在四个这样的组: 1 ((A)(B(C))) 2 \A 3 (B(C)) 4 (C) 组零始终代表整个表达式。

更多详细信息,可查阅JDK文档中java.util.regex 中Pattern类的描述。

四、匹配
 booleanmatches(String regex) 
          告知此字符串是否匹配给定的正则表达式
1、如对QQ号码进行校验:
需求:要求:5~15位,0不能开头,只能是数字。若不使用正则表达式,使用传统的if-else语句进行逐一判断也行,但是代码冗长,效率低:

public static void checkQQ(String qq)//使用时传入QQ号码进行校验 { String regex = "[1-9]\\d{4,14}"; boolean flag = qq.matches(regex); if(flag) System.out.println(qq+"...is ok"); else System.out.println(qq+"... 不合法"); }

2、需求:对邮件地址进行校验。

public static boolean checkMail(String mail) { String reg = "[a-zA-Z0-9_]+@[a-zA-Z0-9]+(\\.[a-zA-Z]+)+";//较为精确的匹配。 reg = "\\w+@\\w+(\\.\\w+)+";//相对不太精确的匹配。 return mail.matches(reg); }

四、切割(String的split()方法)
 String[]split(String regex) 
          根据给定正则表达式的匹配拆分此字符串。
 String[]split(String regex, int limit) 
          根据匹配给定的正则表达式来拆分此字符串。
1、需求:对字符串进行切割获取一系列人名,人名中间有空格(一个或多个空格)

public String[] getNames(String str){

//假如有这样一个字符串

str = "zhangsan lisi wangwu zhaoliu";

regex = " +";//规则是一个或多个空格

String[] names = str.split();

return names;

}

五、替换
 Stringreplace(char oldChar, char newChar) 
          返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的。
 Stringreplace(CharSequence target, CharSequence replacement) 
          使用指定的字面值替换序列替换此字符串所有匹配字面值目标序列的子字符串。
 StringreplaceAll(String regex, String replacement) 
          使用给定的 replacement 替换此字符串所有匹配给定的正则表达式的子字符串。
 StringreplaceFirst(String regex, String replacement) 
          使用给定的 replacement 替换此字符串匹配给定的正则表达式的第一个子字符串。

class RegexDemo { public static void main(String[] args) { String str = "wer1389980000ty1234564uiod234345675f";//将字符串中的数组替换成#。 replaceAllDemo(str,"\\d{5,}","#"); String str1 = "erkktyqqquizzzzzo";//将叠词替换成$.将重叠的字符替换成单个字母。zzzz->z replaceAllDemo(str1,"(.)\\1+","$1");////获取组,"$1"表示前面正则表达式中第一组中的内容

} public static void replaceAllDemo(String str,String reg,String newStr) { str = str.replaceAll(reg,newStr); System.out.println(str); }

}
六、获取
java正则表达式通过java.util.regex 包下的Pattern 类与Matcher 类实现: 
    1、首先引入java 包:java.util.regex 
    2、使用方法如下: 
      

        典型的调用顺序:
①构造一个模式. 
        Pattern p = Pattern.compile("[a-z]*"); 
        ②建造一个匹配器 
        Matcher m = p.matcher(str); 
        ③进行判断,得到结果 
        boolean b = m.matches();
在仅使用一次正则表达式时,可以方便地通过此Pattern类的matcher()方法此方法编译表达式并在单个调用中将输入序列与其匹配。语句
boolean b = Pattern.matches("[a-z]*", "aaaaab");
等效于上面的三个语句,尽管对于重复的匹配而言它效率不高,因为它不允许重用已编译的模式。
此类的实例是不可变的,可供多个并发线程安全使用。Matcher类的实例用于此目的则不安全。
static booleanmatches(String regex, CharSequence input) 
          编译给定正则表达式并尝试将给定输入与其匹配。
Matcher对象中常用的方法
 intend() 
          返回最后匹配字符之后的偏移量。
 intend(int group) 
          返回在以前的匹配操作期间,由给定组所捕获子序列的最后字符之后的偏移量。
 booleanfind() 
          尝试查找与该模式匹配的输入序列的下一个子序列。
 booleanfind(int start) 
          重置此匹配器,然后尝试查找匹配该模式、从指定索引开始的输入序列的下一个子序列。
 Stringgroup() 
          返回由以前匹配操作所匹配的输入子序列。
 Stringgroup(int group) 
          返回在以前匹配操作期间由给

/* 获取:将字符串中的符合规则的子串取出 操作步骤: 1,将正则表达式封装成对象。 2,让正则对象和要操作的字符串相关联。 3,关联后,获取正则匹配引擎。 4,通过引擎对符合规则的子串进行操作,比如取出。 */ import java.util.regex.*; class RegexDemo2 { public static void main(String[] args) { String str = "ming tian jiu yao fang jia le ,da jia。"; String reg = "\\b[a-z]{4}\\b";// \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.group());//用于获取匹配后结果。 //System.out.println("matches:"+m.matches()); while(m.find())//与迭代器类似 { System.out.println(m.group()); System.out.println(m.start()+"...."+m.end()); } } }

七、如何选择
需求一:将这个字符串 "我我...我我...我要..要要...要要...学学学....学学...编编编...编程..程.程程...程...程"转换成 "我要学编程"。
到底用四种功能中的哪一个呢?或者哪几个呢?
思路方式:
  1. 如果只是想知道字符串是否符合某一规则,如用户名,QQ号码,电子邮件格式的校验。此时用匹配
  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")); } }

八、网页爬虫

public static void getMails_1()throws Exception { URL url = new URL("http://192.168.1.254:8080/myweb/mail.html"); URLConnection conn = url.openConnection(); BufferedReader bufIn = new BufferedReader(new InputStreamReader(conn.getInputStream())); String line = null; String mailreg = "\\w+@\\w+(\\.[a-zA-Z0-9]+)+"; Pattern p = Pattern.compile(mailreg); while((line=bufIn.readLine())!=null) { Matcher m = p.matcher(line); while(m.find()) { System.out.println(m.group()); } } }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值