Java基础之《正则表达式》

时间:2023-02-16 22:55:05
2007年2月

RegularExpressions 字符串处理利器

一、前言
1、正则表达式就是用来处理字符串的(查找、替换等)

用途:
  字符串匹配(字符匹配)
  字符串查找
  字符串替换

例如:
  IP地址是否正确
  从网页中揪出email地址
  从网页中揪出链接等

类:
  java.lang.String
  java.util.regex.Pattern
  java.util.regex.Matcher

2、Pattern:是要符合的模式
   Matcher:匹配这种模式产生的结果

二、String类的方法
1、matches
  匹配整个字符串
  返回是否匹配该模式,返回true或flase

2、replaceAll
  替换所有符合模式的字符

三、Matcher类的方法
1、matches
  匹配整个字符串

2、reset
  回到初始开头

3、find
  找一个和模式匹配的子串
  返回true或flase

4、lookingAt
  每次找从开始的位置找起

5、start
  获得子串的起始位置
  必须找到才能输出,否则报错

6、end
  获得子串的结束位置
  必须找到才能输出,否则报错

7、replaceAll
  替换所有匹配到的字串

8、group
  分组

9、注意
  matches永远匹配整个字符串
  find找子串
  matches和find字符串会往后移,用reset回到初始状态
  lookingAt每次从头上开始找

四、表达式说明
(.):一个点代表一个字母
(*):零个或多个
(+):一个或多个
(?):一个或零个
([]):中括号表示值范围, 一个中括号匹配一个字符
({}):尖括号表示出现次数的范围
(\d):代表一位数字
(^):小尖号在中括号里是取反的意思
(\s):代表一个空白字符
(\w):代表构成单词的字符
(^):小尖号在中括号外面是输入的开头
($):代表一行的结尾
(\b):代表单词的边界(空格、空白字符、特殊字符、换行字符)
(.*):组合,零个或多个字母
(分组()):用小括号表示分组,一对儿小括号表示一组
            如果小括号套小括号,数左小括号,第一个左小括号是第一组,第二个左小括号是第二组,以此类推

五、qulifiers
1、有三种限定方式
Greedy quantifiers:贪婪的
Reluctant quantifiers:不情愿的,勉强的
Possessive quantifiers:独占的

Greedy是挑最大的字符吞,如果不匹配一个一个往外吐,匹配到就不匹配了
Reluctant:吞最少的,再一个一个加,匹配到就不匹配了
Possessive:吞最大的,不往外吐

六、其他
马士兵语录:
1、什么样的女人是最有魅力的女人:特别具有幽默感、豁达的女人,大多数女的比较现实。

七、例子程序

下载地址:https://pan.baidu.com/s/1pLDRDyV

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Test {

	public static void main(String[] args) {
		//简单认识正则表达式的概念
		print("abc".matches("..."));
		//替换所有的数字为横杠
		print("a8729a".replaceAll("\\d", "-"));
		
		//先编译,以后匹配效率快
		Pattern p = Pattern.compile("[a-z]{3}"); //匹配3个长度的字符,每个字符是a到z的字符
		Matcher m = p.matcher("fgh"); //匹配器
		print(m.matches()); //返回匹配结果
		//上面3句话可以合并成简单的一句话
		print("fgha".matches("[a-z]{3}"));
		
		//初步认识 . * + ?
		print("a".matches("."));
		print("aa".matches("aa"));
		print("aaaa".matches("a*"));
		print("aaaa".matches("a+"));
		print("".matches("a*"));
		print("aaaa".matches("a?"));
		print("".matches("a?"));
		print("a".matches("a?"));
		print("682570257349057".matches("\\d{3,100}"));
		print("192.168.0.aaa".matches("\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}"));
		print("192".matches("[0-2][0-9][0-9]"));
		
		//范围
		print("a".matches("[abc]"));
		print("a".matches("[^abc]"));
		print("A".matches("[a-zA-Z]"));
		print("A".matches("[a-z]|[A-Z]")); //和[a-zA-Z]一样
		print("A".matches("[a-z[A-Z]]")); //和[a-zA-Z]一样
		print("R".matches("[A-Z&&[RFG]]")); //(取交集)A到Z之中的,并且是RFG三者之一的
		
		//认识 \s \w \d \
		print(" \n\r\t".matches("\\s{4}"));
		print(" ".matches("\\S"));
		print("a_8".matches("\\w{3}"));
		print("abc888%^%".matches("[a-z]{1,3}\\d+[&^#%]+"));
		print("\\".matches("\\\\")); //正则表达式匹配一个反斜线
		
		//POSIX Style
		//print("a".matches("\\p{Lower}"));
		
		//boundary
		print("hello sir".matches("^h.*")); //边界匹配
		print("hello sir".matches(".*ir$"));
		print("hello sir".matches("^h[a-z]{1,3}o\\b.*"));
		print("hellosir".matches("^h[a-z]{1,3}o\\b.*"));
		
		//whilte lines
		print(" \n".matches("^[\\s&&[^\\n]]*\\n$")); //开头是一个空白符但不是一个换行符,出现零次或多次,结尾是换行符
		
		print("aaa 8888c".matches(".*\\d{4}."));
		print("aaa 8888c".matches(".*\\b\\d{4}."));
		print("aaa8888c".matches(".*\\d{4}."));
		print("aaa8888c".matches(".*\\b\\d{4}."));
		
		//email
		print("asdf@asdf.com".matches("[\\w[.-]]+@[\\w[.-]]+\\.[\\w]+"));
		
		//matches find lookingAt
		Pattern p = Pattern.compile("\\d{3,5}");
		String s = "123-34345-234-00";
		Matcher m = p.matcher(s);
		print(m.matches());
		m.reset();
		print(m.find());
		print(m.start() + "-" + m.end());
		print(m.find());
		print(m.start() + "-" + m.end());
		print(m.find());
		print(m.start() + "-" + m.end());
		print(m.find());
		
		print(m.lookingAt());
		print(m.lookingAt());
		print(m.lookingAt());
		print(m.lookingAt());
		
		//replacement
		Pattern p = Pattern.compile("java", Pattern.CASE_INSENSITIVE);
		Matcher m = p.matcher("java Java JAVa JaVa IloveJAVA you hateJava asdfhgkuiewvx");
		//print(m.replaceAll("JAVA"));
		StringBuffer buf = new StringBuffer();
		int i = 0;
		while (m.find()) {
			i++;
			if (i%2 == 0) {
				m.appendReplacement(buf, "java");
			} else {
				m.appendReplacement(buf, "JAVA");
			}
		}
		
		print(m.appendTail(buf));
		
		//group
		Pattern p = Pattern.compile("(\\d{3,5})([a-z]{2})");
		String s = "123aa-34345bb-234cc-00";
		Matcher m = p.matcher(s);
		while (m.find()) {
			print(m.group());
		}
		
		//qulifiers
		Pattern p = Pattern.compile("(.{3,10}?)[0-9]"); //{3,10}后面加?和不加的区别
		String s = "aaaa5bbbb6";
		Matcher m = p.matcher(s);
		if (m.find()) {
			print(m.start() + "-" + m.end());
		} else {
			print("not match!");
		}
		
		//non-capturing groups
		Pattern p = Pattern.compile(".{3}(?=a)"); //?=a 不捕获a
		String s = "44a66b";
		Matcher m = p.matcher(s);
		while(m.find()) {
			print(m.group());
		}
		
		//back references
		Pattern p = Pattern.compile("(\\d\\d)\\1"); //向前引用,后面的东西和第一次找到的东西必须一模一样
		String s = "1212";
		Matcher m = p.matcher(s);
		print(m.matches());
		
		//flags的简写
		Pattern p = Pattern.compile("java", Pattern.CASE_INSENSITIVE);
		//Pattern.CASE_INSENSITIVE的简写
		print("Java".matches("(?i)(java)"));
		
	}

	public static void print(Object o) {
		System.out.println(o.toString());
	}
}