浅入深出Re:正则表达式的养成方法

以下出自图灵丛书精通正则表达式一书,实验遇到的问题及解决方法,记载在此

Java正则的使用姿势

Regular Expressions API

  • Pattern 描述了一种字符串模式。
  • Matcher 测试一个字符串,查看它是否与该模式匹配。
正则表达式结构 符合匹配条件的内容
. 任何字符
? 前面的0或1个字符或数字
* 前面的零 (0) 或更多个字符或数字
+ 前面的一 (1) 或更多个字符或数字
[ ] 一个字符或数字范围
^ 后面的条件的否定条件(即 “非后面的条件”)
/d 任何数字(也可表示为 [0-9])
/D 任何非数字(也可表示为 [^0-9])
/s 任何空格字符(也可表示为 [\n\t\f\r])
/S 任何非空格字符(也可表示为 [^\n\t\f\r])
\w 任何单词字符(也可表示为 [a-zA-Z_0-9])
\W 任何非单词字符(也可表示为 [^\w])
\b 查找位于单词的开头或结尾的匹配
$ 检查行尾是否如下
(?:pattern) 匹配 pattern 但不捕获该匹配的子表达式

Test1 : 找到一个具有以下形式的字符串:A 或 a 后跟零或多个字符,后跟 string。

 //4nd way
        Pattern pattern = Pattern.compile("[Aa].*string");//匹配string字符串之前的0或者更多字符和数字
        Matcher matcher = pattern.matcher("A string");
        boolean didMatch = matcher.matches();
        System.out.println(didMatch);
        int patternStartIndex = matcher.start();
        System.out.println(patternStartIndex);
        int patternEndIndex = matcher.end();
        System.out.println(patternEndIndex);
  • 匹配方法

每个 Java 语言字符串都是一个带索引的字符集合,索引从 0 开始,到字符串长度减 1 结束。Matcher 从 0 开始解析该字符串,寻找与它匹配的结果。完成处理后,Matcher 包含有关在输入字符串中找到(或未找到)匹配结果的信息。如果字符串中包含的元素比您搜索的模式中字符数要多,可以使用 lookingAt() 代替 matches()。

Test2 : 搜索匹配的较长的字符串信息

matches()

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

/**
 * Created by 26645 on 2017/8/31.
 */
public class RegexTest {
    public static void main(String[] args) {
        Pattern p = Pattern.compile(".s");//表示单个字符
        Matcher m= p.matcher("as");
        boolean b =m.matches();

        //2nd way
        boolean b2 = Pattern.compile(".s").matcher("as").matches();

        //3nd way
        boolean b3 = Pattern.matches(".s","as");

        //4nd way
        Pattern pattern = Pattern.compile("[Aa].*string");//匹配string字符串之前的0或者更多字符和数字
        Scanner scan = new Scanner(System.in);
        if (scan.hasNextLine()){
            Matcher matcher = pattern.matcher(scan.nextLine());
            boolean didMatch = matcher.matches();
            System.out.println(didMatch);
            int patternStartIndex = matcher.start();
            System.out.println(patternStartIndex);
            int patternEndIndex = matcher.end();
            System.out.println(patternEndIndex);
        }
        
    }
}

console output : 字符串中包含比模式中更多的内容,查找失败

false
Exception in thread "main" java.lang.IllegalStateException: No match available
    at java.util.regex.Matcher.start(Matcher.java:343)
    at RegexTest.main(RegexTest.java:28)

lookingAt()

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

/**
 * Created by 26645 on 2017/8/31.
 */
public class RegexTest {
    public static void main(String[] args) {
        Pattern p = Pattern.compile(".s");//表示单个字符
        Matcher m= p.matcher("as");
        boolean b =m.matches();

        //2nd way
        boolean b2 = Pattern.compile(".s").matcher("as").matches();

        //3nd way
        boolean b3 = Pattern.matches(".s","as");

        //4nd way
        Pattern pattern = Pattern.compile("[Aa].*string");//匹配string字符串之前的0或者更多字符和数字
        Scanner scan = new Scanner(System.in);
        if (scan.hasNextLine()){
            Matcher matcher = pattern.matcher(scan.nextLine());
            boolean didLookingAt = matcher.lookingAt();
            //boolean didMatch = matcher.matches();
            System.out.println(didLookingAt);
            int patternStartIndex = matcher.start();
            System.out.println(patternStartIndex);
            int patternEndIndex = matcher.end();
            System.out.println(patternEndIndex);
        }

    }
}

console output:匹配失败,lookingAt()方法只匹配正则表达式与文本的开头。

false
Exception in thread "main" java.lang.IllegalStateException: No match available
    at java.util.regex.Matcher.start(Matcher.java:343)
    at RegexTest.main(RegexTest.java:28)

那么如果我们想要在模式匹配中找到非0索引开头的字符串,我们应该怎么做呢?
Bingo! find() 方法,stackoverflow提议传送门

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

/**
 * Created by 26645 on 2017/8/31.
 */
public class RegexTest {
    public static void main(String[] args) {
        Pattern p = Pattern.compile(".s");//表示单个字符
        Matcher m= p.matcher("as");
        boolean b =m.matches();

        //2nd way
        boolean b2 = Pattern.compile(".s").matcher("as").matches();

        //3nd way
        boolean b3 = Pattern.matches(".s","as");

        //4nd way
        Pattern pattern = Pattern.compile("[Aa].*string");//匹配string字符串之前的0或者更多字符和数字
        Scanner scan = new Scanner(System.in);
        String str1="7-11";
        String regex = "-";
        Pattern ptest = Pattern.compile(regex);
        Matcher m1 = ptest.matcher(str1);
        System.out.println(m1.lookingAt());

        if (scan.hasNextLine()){
            Matcher matcher = pattern.matcher(scan.nextLine());
            //boolean didLookingAt = matcher.lookingAt();
            //boolean didMatch = matcher.matches();
            boolean didfind = matcher.find();
            System.out.println(didfind);
            int patternStartIndex = matcher.start();
            System.out.println(patternStartIndex);
            int patternEndIndex = matcher.end();
            System.out.println(patternEndIndex);
        }

    }
}

console output

D:\java\jdk1.8.0_51\bin\java "-javaagent:D:\idea\IntelliJ IDEA 2017.1.4\lib\idea_rt.jar=61963:D:\idea\IntelliJ IDEA 2017.1.4\bin" -Dfile.encoding=UTF-8 -classpath D:\java\jdk1.8.0_51\jre\lib\charsets.jar;D:\java\jdk1.8.0_51\jre\lib\deploy.jar;D:\java\jdk1.8.0_51\jre\lib\ext\access-bridge-64.jar;D:\java\jdk1.8.0_51\jre\lib\ext\cldrdata.jar;D:\java\jdk1.8.0_51\jre\lib\ext\dnsns.jar;D:\java\jdk1.8.0_51\jre\lib\ext\jaccess.jar;D:\java\jdk1.8.0_51\jre\lib\ext\jfxrt.jar;D:\java\jdk1.8.0_51\jre\lib\ext\localedata.jar;D:\java\jdk1.8.0_51\jre\lib\ext\nashorn.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunec.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunjce_provider.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunmscapi.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunpkcs11.jar;D:\java\jdk1.8.0_51\jre\lib\ext\zipfs.jar;D:\java\jdk1.8.0_51\jre\lib\javaws.jar;D:\java\jdk1.8.0_51\jre\lib\jce.jar;D:\java\jdk1.8.0_51\jre\lib\jfr.jar;D:\java\jdk1.8.0_51\jre\lib\jfxswt.jar;D:\java\jdk1.8.0_51\jre\lib\jsse.jar;D:\java\jdk1.8.0_51\jre\lib\management-agent.jar;D:\java\jdk1.8.0_51\jre\lib\plugin.jar;D:\java\jdk1.8.0_51\jre\lib\resources.jar;D:\java\jdk1.8.0_51\jre\lib\rt.jar;E:\kotlin_learn\out\production\kotlin_learn;C:\Users\26645\.IntelliJIdea2017.1\config\plugins\Kotlin\kotlinc\lib\kotlin-runtime.jar;C:\Users\26645\.IntelliJIdea2017.1\config\plugins\Kotlin\kotlinc\lib\kotlin-reflect.jar;E:\kotlin_learn\junit-4.12.jar RegexTest
false
Here is a vbery string
true
8
22

Process finished with exit code 0

  • 正则表达式中的复杂模式

Tips:Wiki 几乎完全基于正则表达式。Wiki 内容基于来自用户的字符串输入,该输入被使用正则表达式解析和格式化。任何用户都可以通过输入一个 wiki 词组在 wiki 中创建另一个主题的链接,这个词组通常是一系列串联的单词,每个单词以一个大写字母开头
匹配目标: HereAllowed is a WikiWord followed by AnotherWikiWord,then SomeWikiWord.

  String input = "HereAllowed is a WikiWord followed by AnotherWikiWord,then SomeWikiWord.";
        Pattern pattern1 = Pattern.compile("[A-Z][a-z]*([A-Z][a-z]*)*");
        Matcher matcher = pattern1.matcher(input);
        while(matcher.find()){
            System.out.println(matcher.group());
        }

console output

D:\java\jdk1.8.0_51\bin\java "-javaagent:D:\idea\IntelliJ IDEA 2017.1.4\lib\idea_rt.jar=62138:D:\idea\IntelliJ IDEA 2017.1.4\bin" -Dfile.encoding=UTF-8 -classpath D:\java\jdk1.8.0_51\jre\lib\charsets.jar;D:\java\jdk1.8.0_51\jre\lib\deploy.jar;D:\java\jdk1.8.0_51\jre\lib\ext\access-bridge-64.jar;D:\java\jdk1.8.0_51\jre\lib\ext\cldrdata.jar;D:\java\jdk1.8.0_51\jre\lib\ext\dnsns.jar;D:\java\jdk1.8.0_51\jre\lib\ext\jaccess.jar;D:\java\jdk1.8.0_51\jre\lib\ext\jfxrt.jar;D:\java\jdk1.8.0_51\jre\lib\ext\localedata.jar;D:\java\jdk1.8.0_51\jre\lib\ext\nashorn.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunec.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunjce_provider.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunmscapi.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunpkcs11.jar;D:\java\jdk1.8.0_51\jre\lib\ext\zipfs.jar;D:\java\jdk1.8.0_51\jre\lib\javaws.jar;D:\java\jdk1.8.0_51\jre\lib\jce.jar;D:\java\jdk1.8.0_51\jre\lib\jfr.jar;D:\java\jdk1.8.0_51\jre\lib\jfxswt.jar;D:\java\jdk1.8.0_51\jre\lib\jsse.jar;D:\java\jdk1.8.0_51\jre\lib\management-agent.jar;D:\java\jdk1.8.0_51\jre\lib\plugin.jar;D:\java\jdk1.8.0_51\jre\lib\resources.jar;D:\java\jdk1.8.0_51\jre\lib\rt.jar;E:\kotlin_learn\out\production\kotlin_learn;C:\Users\26645\.IntelliJIdea2017.1\config\plugins\Kotlin\kotlinc\lib\kotlin-runtime.jar;C:\Users\26645\.IntelliJIdea2017.1\config\plugins\Kotlin\kotlinc\lib\kotlin-reflect.jar;E:\kotlin_learn\junit-4.12.jar RegexTest
HereAllowed
WikiWord
AnotherWikiWord
SomeWikiWord
  • 匹配和操作分组

那么回归上一节,正则表达式复杂模式下匹配大写字母开头的字符串类型,并用小括号进行分隔匹配,但我们只能用这种方法么? 在对字符串操作分组更多时,matcher.group(0),matcher.group(1)的效率显然不理想,所以我们引入"分组"的概念,将匹配得到的字符串作为模板,通过在替换字符串中包含 $0 来引用完整匹配结果,即matcher.group(0).当我们需要制定分组时,只需要指定模板变量$之后的数字下标即可

 //6th way
        String input = "Here is a WikiWord followed by AnotherWikiWord,then SomeWikiWord";
        Pattern pattern = Pattern.compile("[A-Z][a-z]*([A-z][a-z]*)*");
        Matcher mathcer = pattern.matcher(input);
        System.out.println("Before: "+input);
        String result = mathcer.replaceAll("blah$0blah");
        System.out.println("After:"+result);
        String result_update = mathcer.replaceAll("blah$1blah");
        System.out.println("After_update: "+result_update);

console output

D:\java\jdk1.8.0_51\bin\java "-javaagent:D:\idea\IntelliJ IDEA 2017.1.4\lib\idea_rt.jar=52384:D:\idea\IntelliJ IDEA 2017.1.4\bin" -Dfile.encoding=UTF-8 -classpath D:\java\jdk1.8.0_51\jre\lib\charsets.jar;D:\java\jdk1.8.0_51\jre\lib\deploy.jar;D:\java\jdk1.8.0_51\jre\lib\ext\access-bridge-64.jar;D:\java\jdk1.8.0_51\jre\lib\ext\cldrdata.jar;D:\java\jdk1.8.0_51\jre\lib\ext\dnsns.jar;D:\java\jdk1.8.0_51\jre\lib\ext\jaccess.jar;D:\java\jdk1.8.0_51\jre\lib\ext\jfxrt.jar;D:\java\jdk1.8.0_51\jre\lib\ext\localedata.jar;D:\java\jdk1.8.0_51\jre\lib\ext\nashorn.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunec.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunjce_provider.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunmscapi.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunpkcs11.jar;D:\java\jdk1.8.0_51\jre\lib\ext\zipfs.jar;D:\java\jdk1.8.0_51\jre\lib\javaws.jar;D:\java\jdk1.8.0_51\jre\lib\jce.jar;D:\java\jdk1.8.0_51\jre\lib\jfr.jar;D:\java\jdk1.8.0_51\jre\lib\jfxswt.jar;D:\java\jdk1.8.0_51\jre\lib\jsse.jar;D:\java\jdk1.8.0_51\jre\lib\management-agent.jar;D:\java\jdk1.8.0_51\jre\lib\plugin.jar;D:\java\jdk1.8.0_51\jre\lib\resources.jar;D:\java\jdk1.8.0_51\jre\lib\rt.jar;E:\kotlin_learn\out\production\kotlin_learn;C:\Users\26645\.IntelliJIdea2017.1\config\plugins\Kotlin\kotlinc\lib\kotlin-runtime.jar;C:\Users\26645\.IntelliJIdea2017.1\config\plugins\Kotlin\kotlinc\lib\kotlin-reflect.jar;E:\kotlin_learn\junit-4.12.jar RegexTest
Before: Here is a WikiWord followed by AnotherWikiWord,then SomeWikiWord
After:blahHereblah is a blahWikiWordblah followed by blahAnotherWikiWordblah,then blahSomeWikiWordblah
After_update: blahblah is a blahWordblah followed by blahWordblah,then blahWordblah

Process finished with exit code 0
  • 替换字符串
 //6th way
        String input = "Here is a WikiWord followed by AnotherWikiWord,then SomeWikiWord";
        Pattern pattern = Pattern.compile("[A-Z][a-z]*([A-z][a-z]*)*");
        Matcher mathcer = pattern.matcher(input);
        System.out.println("Before: "+input);
        String result = mathcer.replaceAll("blah$0blah");
        System.out.println("After:"+result);
        String result_update = mathcer.replaceAll("blah$1blah");
        System.out.println("After_update: "+result_update);

console output

D:\java\jdk1.8.0_51\bin\java "-javaagent:D:\idea\IntelliJ IDEA 2017.1.4\lib\idea_rt.jar=52384:D:\idea\IntelliJ IDEA 2017.1.4\bin" -Dfile.encoding=UTF-8 -classpath D:\java\jdk1.8.0_51\jre\lib\charsets.jar;D:\java\jdk1.8.0_51\jre\lib\deploy.jar;D:\java\jdk1.8.0_51\jre\lib\ext\access-bridge-64.jar;D:\java\jdk1.8.0_51\jre\lib\ext\cldrdata.jar;D:\java\jdk1.8.0_51\jre\lib\ext\dnsns.jar;D:\java\jdk1.8.0_51\jre\lib\ext\jaccess.jar;D:\java\jdk1.8.0_51\jre\lib\ext\jfxrt.jar;D:\java\jdk1.8.0_51\jre\lib\ext\localedata.jar;D:\java\jdk1.8.0_51\jre\lib\ext\nashorn.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunec.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunjce_provider.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunmscapi.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunpkcs11.jar;D:\java\jdk1.8.0_51\jre\lib\ext\zipfs.jar;D:\java\jdk1.8.0_51\jre\lib\javaws.jar;D:\java\jdk1.8.0_51\jre\lib\jce.jar;D:\java\jdk1.8.0_51\jre\lib\jfr.jar;D:\java\jdk1.8.0_51\jre\lib\jfxswt.jar;D:\java\jdk1.8.0_51\jre\lib\jsse.jar;D:\java\jdk1.8.0_51\jre\lib\management-agent.jar;D:\java\jdk1.8.0_51\jre\lib\plugin.jar;D:\java\jdk1.8.0_51\jre\lib\resources.jar;D:\java\jdk1.8.0_51\jre\lib\rt.jar;E:\kotlin_learn\out\production\kotlin_learn;C:\Users\26645\.IntelliJIdea2017.1\config\plugins\Kotlin\kotlinc\lib\kotlin-runtime.jar;C:\Users\26645\.IntelliJIdea2017.1\config\plugins\Kotlin\kotlinc\lib\kotlin-reflect.jar;E:\kotlin_learn\junit-4.12.jar RegexTest
Before: Here is a WikiWord followed by AnotherWikiWord,then SomeWikiWord
After:blahHereblah is a blahWikiWordblah followed by blahAnotherWikiWordblah,then blahSomeWikiWordblah
After_update: blahblah is a blahWordblah followed by blahWordblah,then blahWordblah
  • Re构造:标识符
    \b为零宽度的字符,一侧是构成单词的字符,另一侧为非单词字符、字符串的开始或结束位置。
    在Java中\w等同于[a-zA-Z0-9_]
    我们以几个合法标识符举例abc,_test,$test
    当匹配到一个字符串时,必定不能以数字型前缀开头,例 : 123abc

构造思路:字符组建立
1.用\b用来分割字符串左侧为构成单词的字符,排除数字型前缀字符串。右侧为非单词字符,排除空格
2.使用[a-zA-Z_]字符组限制右侧出现的字符类型
3.使用\w*字符组匹配自此之前的字符串

 //7th way
        String line = "imooc";
        String Regex_second ="\\b[a-zA-Z_]\\w*";
        Pattern pattern2 = Pattern.compile(Regex_second);
        Matcher matcher2 = pattern2.matcher(line);
        if(matcher2.find()){
            System.out.println(matcher2.group());
        }
    }

console output

D:\java\jdk1.8.0_51\bin\java "-javaagent:D:\idea\IntelliJ IDEA 2017.1.4\lib\idea_rt.jar=49789:D:\idea\IntelliJ IDEA 2017.1.4\bin" -Dfile.encoding=UTF-8 -classpath D:\java\jdk1.8.0_51\jre\lib\charsets.jar;D:\java\jdk1.8.0_51\jre\lib\deploy.jar;D:\java\jdk1.8.0_51\jre\lib\ext\access-bridge-64.jar;D:\java\jdk1.8.0_51\jre\lib\ext\cldrdata.jar;D:\java\jdk1.8.0_51\jre\lib\ext\dnsns.jar;D:\java\jdk1.8.0_51\jre\lib\ext\jaccess.jar;D:\java\jdk1.8.0_51\jre\lib\ext\jfxrt.jar;D:\java\jdk1.8.0_51\jre\lib\ext\localedata.jar;D:\java\jdk1.8.0_51\jre\lib\ext\nashorn.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunec.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunjce_provider.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunmscapi.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunpkcs11.jar;D:\java\jdk1.8.0_51\jre\lib\ext\zipfs.jar;D:\java\jdk1.8.0_51\jre\lib\javaws.jar;D:\java\jdk1.8.0_51\jre\lib\jce.jar;D:\java\jdk1.8.0_51\jre\lib\jfr.jar;D:\java\jdk1.8.0_51\jre\lib\jfxswt.jar;D:\java\jdk1.8.0_51\jre\lib\jsse.jar;D:\java\jdk1.8.0_51\jre\lib\management-agent.jar;D:\java\jdk1.8.0_51\jre\lib\plugin.jar;D:\java\jdk1.8.0_51\jre\lib\resources.jar;D:\java\jdk1.8.0_51\jre\lib\rt.jar;E:\kotlin_learn\out\production\kotlin_learn;C:\Users\26645\.IntelliJIdea2017.1\config\plugins\Kotlin\kotlinc\lib\kotlin-runtime.jar;C:\Users\26645\.IntelliJIdea2017.1\config\plugins\Kotlin\kotlinc\lib\kotlin-reflect.jar;E:\kotlin_learn\junit-4.12.jar RegexTest
imooc
  • Re构造:提取引号内的字符串

构造思路:
1、以引号开始,任意字符,以引号结束。
2、末尾引号左边不能是 \
3、末尾引号左边可以是 \\
4、末尾引号左边不能是 a\

 //8th way
        String line_second ="the\"laozi\"first";
        String Regex = "\"(.*?)(?<![^\\\\]\\\\)\"";
        Pattern pattern3 = Pattern.compile(Regex);
        Matcher matcher = pattern3.matcher(line_second);
        if(matcher.find()){
            System.out.println(matcher.group());
        }

console output

D:\java\jdk1.8.0_51\bin\java "-javaagent:D:\idea\IntelliJ IDEA 2017.1.4\lib\idea_rt.jar=64178:D:\idea\IntelliJ IDEA 2017.1.4\bin" -Dfile.encoding=UTF-8 -classpath D:\java\jdk1.8.0_51\jre\lib\charsets.jar;D:\java\jdk1.8.0_51\jre\lib\deploy.jar;D:\java\jdk1.8.0_51\jre\lib\ext\access-bridge-64.jar;D:\java\jdk1.8.0_51\jre\lib\ext\cldrdata.jar;D:\java\jdk1.8.0_51\jre\lib\ext\dnsns.jar;D:\java\jdk1.8.0_51\jre\lib\ext\jaccess.jar;D:\java\jdk1.8.0_51\jre\lib\ext\jfxrt.jar;D:\java\jdk1.8.0_51\jre\lib\ext\localedata.jar;D:\java\jdk1.8.0_51\jre\lib\ext\nashorn.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunec.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunjce_provider.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunmscapi.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunpkcs11.jar;D:\java\jdk1.8.0_51\jre\lib\ext\zipfs.jar;D:\java\jdk1.8.0_51\jre\lib\javaws.jar;D:\java\jdk1.8.0_51\jre\lib\jce.jar;D:\java\jdk1.8.0_51\jre\lib\jfr.jar;D:\java\jdk1.8.0_51\jre\lib\jfxswt.jar;D:\java\jdk1.8.0_51\jre\lib\jsse.jar;D:\java\jdk1.8.0_51\jre\lib\management-agent.jar;D:\java\jdk1.8.0_51\jre\lib\plugin.jar;D:\java\jdk1.8.0_51\jre\lib\resources.jar;D:\java\jdk1.8.0_51\jre\lib\rt.jar;E:\kotlin_learn\out\production\kotlin_learn;C:\Users\26645\.IntelliJIdea2017.1\config\plugins\Kotlin\kotlinc\lib\kotlin-runtime.jar;C:\Users\26645\.IntelliJIdea2017.1\config\plugins\Kotlin\kotlinc\lib\kotlin-reflect.jar;E:\kotlin_learn\junit-4.12.jar RegexTest
"laozi"
  • Re构造:匹配美元金额(可能包含小数)

构造思路1:将$.转义分别用+截断分别匹配数字型字符

构造思路2:专用d+代替[0-9]匹配组

//9th way
        String dollar="$1000 fdgdfgdfgfdg";
        String Regex = "\\$[0-9]+(\\.[0-9][0-9])?";
        String Regex_first = "\\$\\d+(?:\\.\\d+)?";
        Pattern pattern = Pattern.compile(Regex_first);
        Matcher matcher = pattern.matcher(dollar);
        if(matcher.find()){
            System.out.println(matcher.group());
        }

console output

D:\java\jdk1.8.0_51\bin\java "-javaagent:D:\idea\IntelliJ IDEA 2017.1.4\lib\idea_rt.jar=55131:D:\idea\IntelliJ IDEA 2017.1.4\bin" -Dfile.encoding=UTF-8 -classpath D:\java\jdk1.8.0_51\jre\lib\charsets.jar;D:\java\jdk1.8.0_51\jre\lib\deploy.jar;D:\java\jdk1.8.0_51\jre\lib\ext\access-bridge-64.jar;D:\java\jdk1.8.0_51\jre\lib\ext\cldrdata.jar;D:\java\jdk1.8.0_51\jre\lib\ext\dnsns.jar;D:\java\jdk1.8.0_51\jre\lib\ext\jaccess.jar;D:\java\jdk1.8.0_51\jre\lib\ext\jfxrt.jar;D:\java\jdk1.8.0_51\jre\lib\ext\localedata.jar;D:\java\jdk1.8.0_51\jre\lib\ext\nashorn.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunec.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunjce_provider.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunmscapi.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunpkcs11.jar;D:\java\jdk1.8.0_51\jre\lib\ext\zipfs.jar;D:\java\jdk1.8.0_51\jre\lib\javaws.jar;D:\java\jdk1.8.0_51\jre\lib\jce.jar;D:\java\jdk1.8.0_51\jre\lib\jfr.jar;D:\java\jdk1.8.0_51\jre\lib\jfxswt.jar;D:\java\jdk1.8.0_51\jre\lib\jsse.jar;D:\java\jdk1.8.0_51\jre\lib\management-agent.jar;D:\java\jdk1.8.0_51\jre\lib\plugin.jar;D:\java\jdk1.8.0_51\jre\lib\resources.jar;D:\java\jdk1.8.0_51\jre\lib\rt.jar;E:\kotlin_learn\out\production\kotlin_learn;C:\Users\26645\.IntelliJIdea2017.1\config\plugins\Kotlin\kotlinc\lib\kotlin-runtime.jar;C:\Users\26645\.IntelliJIdea2017.1\config\plugins\Kotlin\kotlinc\lib\kotlin-reflect.jar;E:\kotlin_learn\junit-4.12.jar RegexTest
$1000

  • Re构造:HTML标签

div标签(不含属性)正则式 : (?<=<div>).*(?=</div>)
div标签(含属性)正则式 : <div[^>]*>[^<>]*

Tips : 零宽断言
用于查找在某些内容(但并不包括这些内容)之前或之后的东西,也就是说它们像 \b ^ $ \< \>这样的锚定作用,仅仅用于指定一个位置,不参与内容匹配,这个位置应该满足一定的条件(即断言),因此它们也被称为零宽断言。 断言用来声明一个应该为真的事实。正则表达式中只有当断言为真时才会继续进行匹配

(?<=<div>).*(?=</div>)正则解析

  • (?<=<div>) 先从要匹配的字符串中的最左端找到第一个<div>,然后再匹配其后面的表达式,若无法匹配则继续查找第二个 <div> 再匹配第二个 <div> 后面的字符串,若能匹配则匹配。
  • (?=</div>) 从要匹配的字符串中的最右端找到第一个 </div> (然后 再匹配其前面的表达式,若无法匹配则继续查找第二个 </div> 再匹配第二个 </div> 前面的字符串,若能匹配则匹配
  • .* 在确定搜索范围之后,匹配范围内的任意字符

Tips : 贪婪模式
只要符合要求就一直匹配下去,直到无法匹配为止,即上面的结果就是2和3都存在,就往大的取!只取上限,包括、+、?都是一样的,例如ab.zz匹配abcxxzzsfewzzq的结果是abcxxzzsfewzz,并没有在abcxxzz处停止,而是直到最后的zzq不能再匹配时才停止匹配!

TestGreedyRegex.java

//13th way
        String test="a<tr>aava</tr>abb ";
        String reg="<.+>";
        System.out.println(test.replaceAll(reg,"###"));

console output

D:\java\jdk1.8.0_51\bin\java "-javaagent:D:\idea\IntelliJ IDEA 2017.1.4\lib\idea_rt.jar=61058:D:\idea\IntelliJ IDEA 2017.1.4\bin" -Dfile.encoding=UTF-8 -classpath D:\java\jdk1.8.0_51\jre\lib\charsets.jar;D:\java\jdk1.8.0_51\jre\lib\deploy.jar;D:\java\jdk1.8.0_51\jre\lib\ext\access-bridge-64.jar;D:\java\jdk1.8.0_51\jre\lib\ext\cldrdata.jar;D:\java\jdk1.8.0_51\jre\lib\ext\dnsns.jar;D:\java\jdk1.8.0_51\jre\lib\ext\jaccess.jar;D:\java\jdk1.8.0_51\jre\lib\ext\jfxrt.jar;D:\java\jdk1.8.0_51\jre\lib\ext\localedata.jar;D:\java\jdk1.8.0_51\jre\lib\ext\nashorn.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunec.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunjce_provider.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunmscapi.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunpkcs11.jar;D:\java\jdk1.8.0_51\jre\lib\ext\zipfs.jar;D:\java\jdk1.8.0_51\jre\lib\javaws.jar;D:\java\jdk1.8.0_51\jre\lib\jce.jar;D:\java\jdk1.8.0_51\jre\lib\jfr.jar;D:\java\jdk1.8.0_51\jre\lib\jfxswt.jar;D:\java\jdk1.8.0_51\jre\lib\jsse.jar;D:\java\jdk1.8.0_51\jre\lib\management-agent.jar;D:\java\jdk1.8.0_51\jre\lib\plugin.jar;D:\java\jdk1.8.0_51\jre\lib\resources.jar;D:\java\jdk1.8.0_51\jre\lib\rt.jar;E:\kotlin_learn\out\production\kotlin_learn;C:\Users\26645\.IntelliJIdea2017.1\config\plugins\Kotlin\kotlinc\lib\kotlin-runtime.jar;C:\Users\26645\.IntelliJIdea2017.1\config\plugins\Kotlin\kotlinc\lib\kotlin-reflect.jar;E:\kotlin_learn\junit-4.12.jar RegexTest
a###abb 

<div[^>]*>[^<>]*</div[^>]*>正则解析

  • [^>]*优先匹配排除 >的部分,回归上文,贪婪模式是一种最大匹配,在找到符合条件的字符会继续搜索下去,但当搜索到最后时,发现不能成功匹配 >,于是按照原路回退,<div>标签至此搜索完成。
  • [^<>]*由于我们的目标是匹配<div>标签部分,所以在确定<>内无多余的尖括号,以及排除掉结束标签之后,*继续往下搜索,遇到结束标签则重复步骤1

过滤div标签

 String _input="<div>hhhhhhh</div>";
        String Regex ="<div[^>]*>[^<>]* ";
        String Regex_test="(?<=<div>).*(?=</div>)";
        Pattern pattern = Pattern.compile(Regex);
        Matcher matcher = pattern.matcher(etreeHtml);
        if(matcher.find()){
            System.out.println(matcher.group());
        }

img标签src正则式 : src\\s*=\\s*\"?(.*?)(\"|>|\\s+)
img标签(包括括号) : <img.*src\\s*=\\s*(.*?)[^>]*?>
过滤img标签

 String _input ="<img src=image/ad1.gif width=\"128\" height=\"36\"/>![](image/ad2.gif)";
        String Regex ="src\\s*=\\s*\"?(.*?)(\"|>|\\s+)";
        Pattern pattern = Pattern.compile(Regex);
        Matcher matcher = pattern.matcher(_input);
        boolean notice = matcher.find();
        System.out.println(notice);
        if(matcher.find()){
            System.out.println(matcher.group());
        }

style标签正则式:<[\s]*?style[^>]*?>[\s\S]*?<[\s]*?\/[\s]*?style[\s]*?>

Tips : 勉强模式:
如果说贪婪模式是最大匹配,那么勉强模式就是一种最小匹配。 Java是支持勉强模式的,勉强模式的表示方式是重复次数字符后面紧跟一个?,例如??就表示勉强模式的?+?就表示勉强模式的+*?就表示勉强模式的*{ }?就表示勉强模式的{ };其意义为一找到符合要求的就立马匹配成功,不再管后面的序列,在勉强模式下*匹配0个,+匹配一个,?匹配0个,而{ }只匹配下限

TestReluctantlyRegex

//13th way
        String test="a<tr>aava</tr>abb ";
        String reg="<.+?>";
        System.out.println(test.replaceAll(reg,"###"));

console output

D:\java\jdk1.8.0_51\bin\java "-javaagent:D:\idea\IntelliJ IDEA 2017.1.4\lib\idea_rt.jar=65466:D:\idea\IntelliJ IDEA 2017.1.4\bin" -Dfile.encoding=UTF-8 -classpath D:\java\jdk1.8.0_51\jre\lib\charsets.jar;D:\java\jdk1.8.0_51\jre\lib\deploy.jar;D:\java\jdk1.8.0_51\jre\lib\ext\access-bridge-64.jar;D:\java\jdk1.8.0_51\jre\lib\ext\cldrdata.jar;D:\java\jdk1.8.0_51\jre\lib\ext\dnsns.jar;D:\java\jdk1.8.0_51\jre\lib\ext\jaccess.jar;D:\java\jdk1.8.0_51\jre\lib\ext\jfxrt.jar;D:\java\jdk1.8.0_51\jre\lib\ext\localedata.jar;D:\java\jdk1.8.0_51\jre\lib\ext\nashorn.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunec.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunjce_provider.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunmscapi.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunpkcs11.jar;D:\java\jdk1.8.0_51\jre\lib\ext\zipfs.jar;D:\java\jdk1.8.0_51\jre\lib\javaws.jar;D:\java\jdk1.8.0_51\jre\lib\jce.jar;D:\java\jdk1.8.0_51\jre\lib\jfr.jar;D:\java\jdk1.8.0_51\jre\lib\jfxswt.jar;D:\java\jdk1.8.0_51\jre\lib\jsse.jar;D:\java\jdk1.8.0_51\jre\lib\management-agent.jar;D:\java\jdk1.8.0_51\jre\lib\plugin.jar;D:\java\jdk1.8.0_51\jre\lib\resources.jar;D:\java\jdk1.8.0_51\jre\lib\rt.jar;E:\kotlin_learn\out\production\kotlin_learn;C:\Users\26645\.IntelliJIdea2017.1\config\plugins\Kotlin\kotlinc\lib\kotlin-runtime.jar;C:\Users\26645\.IntelliJIdea2017.1\config\plugins\Kotlin\kotlinc\lib\kotlin-reflect.jar;E:\kotlin_learn\junit-4.12.jar RegexTest
a###aava###abb 

<[\s]*?style[^>]*?>[\s\S]*?<[\s]*?\/[\s]*?style[\s]*?>正则解析 :

  • [\s]*?为了排除设计者在开发过程中出现不慎输入空格的情况,在匹配一个空格字符后,继续匹配style标签。
  • 如果失败,再匹配一个空格字符,看是否有匹配style的可能,如是,继续向下搜索,匹配成功一个字符后,继续匹配>,重复步骤1
  • [\s\S]*?在我们输入style标签关联样式表之后,通常会换行添加属性,在遇到下一个<之前,这些换行字符是不可忽略的,如果忽略。对于换行的style标签内则匹配失败
  • [\s]*?排除结束标签多余的空格,\/为java字符转义,在此无意义

过滤style标签:

//        //10th
        StringBuilder etreeHtml =new StringBuilder("<html>\n" +
                "<head>\n" +
                "    <meta charset=\"utf-8\" />\n" +
                "    <title>HTML Editor</title>\n" +
                "    <style type=\"text/css\">\n" +
                "        .main { float: left;\n" +
                "        width: 100%; }\n" +
                " \n" +
                "        #editor { float: left;\n" +
                "        width: 49%;\n" +
                "        height: 600px;\n" +
                "        resize: none; }\n" +
                " \n" +
                "        #page { float: right;\n" +
                "        width: 49%;\n" +
                "        height: 600px;}\n" +
                "    </style>\n" +
                "</head>\n" +
                " \n" +
                "<body>\n" +
                "    <div class=\"main\">\n" +
                "        <p style=\"float:left; width:49%; color:red;\">This is your code.</p>\n" +
                "        <p style=\"float:right; width:49%; color:red;\">This is your page.</p>\n" +
                "    </div>\n" +
                " \n" +
                "    <div class=\"main\">\n" +
                "        <textarea id=\"editor\" onkeyup=\"showPage()\"></textarea>\n" +
                "        <div id=\"page\"></div>\n" +
                "    </div>\n" +
                "    <div>\n"+
                "      gfgfgfgfg\n"+
                "     </div>"+
                " \n" +
                "    <script type=\"text/javascript\">\n" +
                "        function showPage(){\n" +
                "            code = document.getElementById('editor').value;\n" +
                "            page = document.getElementById('page');\n" +
                "            page.innerHTML = code;\n" +
                "        }\n" +
                "    </script>\n" +
                " \n" +
                "</body>\n" +
                "</html>");
        String Regex = "(?id)<style\\s+(.*?)/?>";//匹配独立的img tags
        String Width_Regex = "(?ix)\\bwidth:(\\S+)";
        //定义style的正则表达式{或<style[^>]*?>[\\s\\S]*?<\\/style>
        String regEx_style = "<[\\s]*?style[^>]*?>[\\s\\S]*?<[\\s]*?\\/[\\s]*?style[\\s]*?>";
//        Matcher mStyle = Pattern.compile(Regex).matcher(etreeHtml);
//        Matcher mWidth =Pattern.compile(Width_Regex).matcher(etreeHtml);
        Pattern pattern = Pattern.compile(regEx_style);
        Matcher mStyle = pattern.matcher(etreeHtml);
        if(mStyle.find()){
            System.out.println(mStyle.group());
        }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 156,757评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,478评论 1 289
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,540评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,593评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,903评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,329评论 1 210
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,659评论 2 309
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,383评论 0 195
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,055评论 1 238
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,337评论 2 241
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,864评论 1 256
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,227评论 2 251
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,820评论 3 231
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,999评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,750评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,365评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,260评论 2 258

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,087评论 18 139
  • 初衷:看了很多视频、文章,最后却通通忘记了,别人的知识依旧是别人的,自己却什么都没获得。此系列文章旨在加深自己的印...
    DCbryant阅读 3,895评论 0 20
  • 9.19--9.23 第7章 正则表达式 正则表达式是一个拆分字符串并查询相关信息的过程。 推荐练习网站: js ...
    如201608阅读 950评论 0 4
  • 百年修得同船渡,那么同住一间病房不知道是修行多少年得来的缘,一起经历痛苦、相互给予鼓励,这是最真最朴实的缘。 住院...
    蓝蝶landie阅读 437评论 2 2
  • 昨日,好友F给我打电话,聊了装修房子的辛苦与拮据,然后说调动工作成功,可是她对原来工作单位及其不舍,而且需要租房子...
    五月的雪雪雪雪阅读 93评论 0 0