浅入深出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 = "\"(.*?)(?

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标签(含属性)正则式 : ]*>[^<>]*

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

(?<=

).*(?=
)正则解析

  • (?<=
    ) 先从要匹配的字符串中的最左端找到第一个
    ,然后再匹配其后面的表达式,若无法匹配则继续查找第二个
    再匹配第二个
    后面的字符串,若能匹配则匹配。
  • (?=
) 从要匹配的字符串中的最右端找到第一个
(然后 再匹配其前面的表达式,若无法匹配则继续查找第二个
再匹配第二个
前面的字符串,若能匹配则匹配
  • .* 在确定搜索范围之后,匹配范围内的任意字符
  • Tips : 贪婪模式
    只要符合要求就一直匹配下去,直到无法匹配为止,即上面的结果就是2和3都存在,就往大的取!只取上限,包括、+、?都是一样的,例如ab.zz匹配abcxxzzsfewzzq的结果是abcxxzzsfewzz,并没有在abcxxzz处停止,而是直到最后的zzq不能再匹配时才停止匹配!

    TestGreedyRegex.java

    //13th way
            String test="aaavaabb ";
            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 
    

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

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

    过滤div标签

     String _input="
    hhhhhhh
    "; String Regex ="]*>[^<>]* "; String Regex_test="(?<=
    ).*(?=
    )"; 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标签

     String _input ="![](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="aaavaabb ";
            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("\n" +
                    "\n" +
                    "    \n" +
                    "    HTML Editor\n" +
                    "    \n" +
                    "\n" +
                    " \n" +
                    "\n" +
                    "    
    \n" + "

    This is your code.

    \n" + "

    This is your page.

    \n" + "
    \n" + " \n" + "
    \n" + " \n" + "
    \n" + "
    \n" + "
    \n"+ " gfgfgfgfg\n"+ "
    "+ " \n" + " \n" + " \n" + "\n" + ""); String Regex = "(?id)";//匹配独立的img tags String Width_Regex = "(?ix)\\bwidth:(\\S+)"; //定义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()); }

    你可能感兴趣的:(浅入深出Re:正则表达式的养成方法)