美文网首页程序员
浅入深出Re:正则表达式的养成方法

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

作者: 语落心生 | 来源:发表于2017-08-31 08:39 被阅读0次

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

    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());
            }
    

    相关文章

      网友评论

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

        本文链接:https://www.haomeiwen.com/subject/rimfjxtx.html