`

算法(五)正则表达式-Regex

 
阅读更多

 

js六种正则表达式方法:matchs,test

        正则表达式方法:reg.test(str),exec()

        String对象方法:str.match(reg),search(),replace(),split()

 

js最常用test

        /\s+\w+\s+/.test("  llyu ");对

        "/\s+\w+\s+/".test("  llyu ")错

 

js正则语法

        g (全文查找) 

        i (忽略大小写) 

        m (多行查找) 

        用法/a/gi;

        "/"为开始和结束标志

js正则用例

        String.prototype.trim=function(){

                return this.replace(/(^\s+)|(\s+$)/g,"");

        }

 

 

java两种正则表达式方法:pattern,String

        Pattern类

                 Pattern p = Pattern.compile("(?<!c)a(\\d+)bd"); 

                 Matcher m = p.matcher("da12bca3434bdca4343bdca234bm"); 

                 while(m.find()){ 

                   System.out.println(m.group(1)); //我们只要捕获组1的数字即可。结果 3434 

                   System.out.println(m.group(0)); // 0组是整个表达式,看这里,并没有提炼出(?<!c)的字符 。结果 a3434bd 

                 } 

 

 

分组,使用小括号"()"来指定

分组可以分为两种形式,捕获组和非捕获组。

 

捕获组 可以用“Back引用”

        引用前面的表达式所捕获到的文本序列(是文本不是正则表达式)

        \1(组1)就是对引号这个分组的引用,

 

非捕获组:为了节省内存等开销;以(?)开头

        5中常见非捕获组

        (?:X) X,作为非捕获组 

        (?=X ) 零宽度正先行断言。仅当子表达式 X 在 此位置的右侧匹配时才继续匹配。例如,\w+(?=\d) 与后跟数字的单词匹配,而不与该数字匹配。此构造不会回溯。 

        (?!X) 零宽度负先行断言。仅当子表达式 X 不在 此位置的右侧匹配时才继续匹配。例如,例如,\w+(?!\d) 与后不跟数字的单词匹配,而不与该数字匹配。 

        (?<=X) 零宽度正后发断言。仅当子表达式 X 在 此位置的左侧匹配时才继续匹配。例如,(?<=19)99 与跟在 19 后面的 99 的实例匹配。此构造不会回溯。 

        (?<!X) 零宽度负后发断言。仅当子表达式 X 不在此位置的左侧匹配时才继续匹配。例如,(?<!19)99 与不跟在 19 后面的 99 的实例匹配 

 

 

 

ab33cd55cd66cd

ab(.*)cd        \1得到33cd55cd66

ab(.*?)cd        \1得到33

 

 

//匹配不包含"party"-----"((?!party).)*"

Ju(ne|ly)不必写成ju((ne)|(jly))

 

 

Pattern p = Pattern.compile(".*?(?<!c)a(\\d+)bd.*?");

Matcher m = p.matcher("dxa34bdza43bdca23bm"); 

while(m.find()){ 

        System.out.println(m.start()+"-->"+m.end());

        System.out.println(m.group(1));

}

结果:

0-->7

34

7-->13

43

 

Pattern p = Pattern.compile("^.*?(?<!c)a(\\d+)bd.*?$");

结果:

0-->19

34

 

Pattern p = Pattern.compile(".*?(?<!c)a(\\d+)bd.*?$");

0-->19

34

 

Pattern p = Pattern.compile("^.*?(?<!c)a(\\d+)bd.*?");

结果:

0-->7

34

 

Pattern p = Pattern.compile(".*(?<!c)a(\\d+)bd.*");

结果:

0-->19

43

 

 

 

贪婪匹配

        a.*b 将匹配满足条件最长的字符串 a=====b=====b 

        工作方式: 

        首先将:a=====b=====b=== 全部吃掉,从右边一个一个地吐出来 

        1. a=====b=====b=== 不匹配,吐出一字符 

        2. a=====b=====b== 不匹配,再吐出一字符 

        3. a=====b=====b= 不匹配,再吐出一字符 

        4. a=====b=====b 匹配了,结束。

懒惰匹配

        a.*? 将匹配满足条件最短的字符串 a=====b 

        工作方式: 

        1. a 不能匹配表达式,继续吃 

        2. a= 不能匹配表达式,继续吃 

        3. a== 不能匹配表达式,继续吃 

        4. a=== 不能匹配表达式,继续吃 

        5. a==== 不能匹配表达式,继续吃 

        6. a===== 不能匹配表达式,继续吃 

        7. a=====b 呵呵,终于能匹配表达式了,匹配结束。 

 

 

 

如果学过编译原理的话应该知道 NFA, 

Java 中正则表达式引擎采用的就是 NFA。反正我是没学过编译原理,也不懂“非确定型有穷自动机”

 

按匹配拆分下 

dxa34bdz a  43    bd  ca23bm 

.*      a  \\d+  bd  .* 

整个串就完全符合匹配所以根本不需要去掉末尾字符了 

 

 

 

 

 

 

 

//                Pattern p = Pattern.compile("Brand=[0-9]{1,3}(&page=[0-9]+)?$");

                Pattern p = Pattern.compile("Brand=[0-9]{1,3}(&page=[0-9]+)?");

                Matcher m = p.matcher("Brand=31&page=1a2"); 

                while(m.find()){ 

                        System.out.println(m.start()+"-->"+m.end());

                        System.out.println(m.group(1));

                }

 

                String reg="Brand=[0-9]{1,3}(&page=[0-9]+)?";

                String str="Brand=31&page=1a2"; 

                System.out.println(str.matches(reg));

 

结果:

0-->15

&page=1

false

 

str.matcher(reg)检查str完全符合reg,故此时"^","$"对reg可有可无 

p.matcher(str)检查str是否包含符合reg的子串,故此时"^","$"对reg是有作用的

 

脚本放在 <body>的最后比较好,不会阻塞浏览器的下载线程, 

可以比较一下效果,会快很多,尤其是在带图片的页面中。  

 

(?idmsux-idmsux:X)  X,作为带有给定标志 on - off 的非捕获组 

(?=X) X,通过零宽度的正 lookahead 

(?!X) X,通过零宽度的负 lookahead 

(? <=X) X,通过零宽度的正 lookbehind 

 

"abc(?i)def(?-i)g"

 

就表示abcg为小写 deg可大写的模式 

 

捕获组,可以被记录下来放于内存中以便反向引用

非捕获组,可以提高匹配效率,节省内存 

 

(?i) 也可以启用不区分大小写的匹配。 

那"abc(?i)def(?-i)g" 

 

Ju(?:ne|ly)

(?i) 打开忽略大小写开关,(?-i) 关掉忽略大小写开关,或者也可以 

写成:abc(?i:def)g

 

 

Pattern p = Pattern.compile("(? <= <(\\w+)>)"); 

Matcher m = p.matcher(textStr); 

 

怎么提示我(? <= <(\\w+)>) 

红色的部分出错 

 

Exception in thread "main" java.util.regex.PatternSyntaxException: Look-behind group does not have an obvious maximum length near index 10 

(? <= <(\w+)>)

lookbehind 其中所指定的字符必须是指定数量的,不能用 * + 之类的,但可以用 {0, 100} 这种确定型的。 

 

lookahead 没有这种限制。 

 

 

\1 这个是反向引用,只是记住 9 个捕获组 \10 表示组 1 和字符 0。

 

 

                 String str = "<b>aaaa</b>\n" +

         "<h1>bbbbb</h1>\n" +

         "<book>adfasdfadfasa\nsdfasdfadfasdf</book>\n" +

         "<b>aaaa</b>";

 

//                 Pattern pattern = Pattern.compile("(?<=<(.{1,100}?)>)(?s:.)*?(?=</\\1>)");

                 Pattern pattern = Pattern.compile("(?<=<(.{1,100}?)>)(?s:.)*?(?=</\\1>)");

                 Matcher matcher = pattern.matcher(str);

                 while(matcher.find()) {

                     System.out.println(matcher.group());

                     System.out.println();

                 }

 

 

(? <= <(\\w{0,100})>).*(?= </\\1) 

和 

(? <= <(.{1,100}?)>)(?s:.)*?(?= </\\1>) 

这个有哪些区别啊? 

就加了一个Pattern.DOTALL? 

在 dotall 模式中,表达式 . 可以匹配任何字符,包括行结束符。默认情况下,此表达式不匹配行结束符。 

 

为什么你这个会匹配对称的啊? 我看不出里面的奥妙,能不能再解释一下啊? 

 

对了为什么{1,100}后面加一个?号呢,我去了好象不行 

还有(?s:.)*?也加了一个?号呢)? 

我知道加?是代表勉强是吧,能不能通俗一点给我讲一下啊? 

去了,为什么不行呢?奇怪 

谢谢先

 

(?s:.) 将这个点用于 DOTALL 模式下,因为 <book>... </book> 中我加了个“\n”。 

 
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics