以下是博主觉得一篇比较OK的教程。
/**
* 一、匹配字符串
*/
String str = "you[0]";
//完全匹配:
List<String> all01 = ReUtil.findAll("you", str, 0);
System.out.println(all01);
//完全匹配:符号转义
List<String> all02 = ReUtil.findAll("you\\[0\\]", str, 0);
System.out.println(all02);
//模糊匹配:横向【ab后出现1~3个c结尾d】 注意:出现5到无限个{5,}
List<String> all03 = ReUtil.findAll("abc{1,3}d", "abcccd", 0);
System.out.println(all03);
//模糊匹配:纵向【a出现后 中间是1或2 结尾是c】
List<String> all04 = ReUtil.findAll("a[12]c", "abc a1c a2c a100c", 0);
System.out.println(all04);
//模糊匹配:横向纵向【a出现后 中间是0~3个数字 结尾是c】
List<String> all05 = ReUtil.findAll("a[\\d]{0,3}c", "ac abc a1c a2c a100c", 0);
System.out.println(all05);
//范围简写:字符范围:a-zA-Z0-9...
List<String> all06 = ReUtil.findAll("a[0-9]{0,3}c", "ac abc a1c a2c a100c", 0);
System.out.println(all06);
//排除:a出现后,中间出现一个单位,但不能是数字,结尾是c
List<String> all07 = ReUtil.findAll("a[^0-9]c", "ac abc a1c a2c a100c", 0);
System.out.println(all07);
//贪婪(默认):尽可能多的匹配,即,中间尽可能匹配6个字符,然后5个...直到匹配为止
List<String> all08 = ReUtil.findAll("a[a-z]{2,6}", "a ab abc abcd abcde", 0);
System.out.println(all08);
//惰性(加上?):尽可能少的匹配,即,中间尽可能匹配2个字符,然后3个...直到匹配为止
List<String> all09 = ReUtil.findAll("a[a-z]{2,6}?", "a ab abc abcd abcde", 0);
System.out.println(all09);
//并行(默认是惰性啊,前一个匹配到了后一个不再参与):两个正则表达式 用|隔开
List<String> all10 = ReUtil.findAll("a[a-z]|a[0-9]", "a ab abc abcd abcde a1 a2 a3", 0);
System.out.println(all10);
//分组:即将多个字符当做一个单位进行匹配,比如匹配连续的ab
List<String> all11 = ReUtil.findAll("(ab)+", "a ab aba abab ababab", 0);
System.out.println(all11);
// ?={0,1} 0或1次; +={1,} 1到无限次; *={0,} 0到无限次
/**
* 案例:content:<div id="container" class="main"></div>
* 如何匹配出 id=”container“,其中container是不确定的
* 1. id="[a-z]*" 这种形式表示,双引号中间可以有0-无限个字符;可以匹配到,但是container可能含有数字特殊字符等等
* 2. id=".*" 这种形式表示,双引号中间可以有无限个单位,其中引号“ 也会被当做一个单位匹配,默认是贪婪模式,尽可能多的匹配,直到最后一个引号为止,所以结果是:id="container" class="main"
* 3. id=".*?" 这是第二种的惰性形式,尽可能少的匹配,匹配到第一个就停止。(效率低)
* 4. id="[^"]*" 这种形式表示,双引号中间除了引号都可以。
*/
List<String> all12 = ReUtil.findAll("id=\"[a-z]*\"", "<div id=\"container\" class=\"main\"></div>", 0);
System.out.println(all12);
/**
* 二、匹配位置
*/
// 匹配字符的开头和结尾 ^表示开头位置,$表示结尾位置:这里注意^表示开头位置,[^xxx]表示取反
String s = "Hello World";
// 案例:在字符串开头和结尾加上#
String e = s.replaceAll("^|$", "#");
System.out.println(e);
// \b单词边界 \B非单词边界,即\b表示每个的单词的开头和结尾,\B则相反,表示非单词开头和结尾
String b = s.replaceAll("\\b", "#");
//#Hello# #World#
System.out.println(b);
String bb = s.replaceAll("\\B", "#");
//H#e#l#l#o W#o#r#l#d
System.out.println(bb);
//(?=p)和(?!p) 表示p前面的位置、非p前面的位置
//将所有不是以左括号结尾的avg单词替换成max
//avg[^(] 可以匹配到所有非左括号结尾的avg单词,但是包括了非左括号。
//avg(?=[^(]) 直接匹配到avg进行替换
/**
* 三、提取数据
*/
// 匹配日期格式
String date = "2017-06-12";
List<String> all13 = ReUtil.findAll("\\d{4}-\\d{2}-\\d{2}", date, 0);
//2017-06-12
System.out.println(all13);
//但是我们现在需要 2017 06 12 这三组数据,怎么办呢?
//2017-06-12
Set<String> all14 = ReUtil.findAll("(\\d{4})-(\\d{2})-(\\d{2})", date, 0, new HashSet<>());
//2017
Set<String> all15 = ReUtil.findAll("(\\d{4})-(\\d{2})-(\\d{2})", date, 1, new HashSet<>());
//06
Set<String> all16 = ReUtil.findAll("(\\d{4})-(\\d{2})-(\\d{2})", date, 2, new HashSet<>());
//12
Set<String> all17 = ReUtil.findAll("(\\d{4})-(\\d{2})-(\\d{2})", date, 3, new HashSet<>());
//2017-06-12, 2017, 06, 12
List<String> all18 = ReUtil.getAllGroups(PatternPool.get("(\\d{4})-(\\d{2})-(\\d{2})", Pattern.DOTALL), date);
案例一:获取特定标签中的内容(贪婪匹配)
public static void main(String[] args) {
String s = "<pre><code class=\"language-java\"> <br/>新中国 <br/> </code></pre><p><br></p><p><br></p>";
/**
* 目标:提取出<code></code>标签中的数据,即: <br/>新中国 <br/>
* 1.<code>.*</code>;可以定位基础标签,但是有class属性就没办法了
* 2.<code.*>.*</code>;可以定位有class属性的code标签,但是因为标签内容中存在>,会引发贪婪
* 3.<code.*?>.*</code>;使用惰性定位,但是无法精确提取想要的数据
* 4.<code.*?>(.*)</code>;通过分组可以拿到标签内的数据了。
*/
List<String> allGroups = ReUtil.getAllGroups(PatternPool.get("<code.*?>(.*)</code>", Pattern.DOTALL), s);
for (String allGroup : allGroups) {
System.out.println(allGroup);
}
}
案例二:获取多个特定标签内容(惰性匹配)
re.findall('<record>[\s\S]*?/record>',html_str)
案例三:匹配空
re.findall('^(?![\s\S])',html_str)