zoukankan      html  css  js  c++  java
  • 转载: java 正则式,正则表达式,多行匹配,不以某某开头,不区分大小写...

    文章出处:http://topic.csdn.net/u/20080627/14/8a91b33a-f35c-4303-85b5-e0a8da462202.html

    1 多行匹配 
    2 不以某某开头 ,比如不以www开头 
    3 不区分大小写 
    4 2个单元的或操作,比如  www ¦ 3w 都可以这种

    火龙果回答:

    1:多行匹配 

    在默认的情况下 . 是不能匹配行结束符的(行结束符有 6 个,具体的可以看看 Pattern 的 API DOC) 
    同样,可以像不匹配大小写匹配那样使用编译参数:Pattern.DOTALL 

    如果还得区分大小写的话,还得加上上面说到的 Pattern.CASE_INSENSITIVE 这个,举个例子:

    Java代码 < type="application/x-shockwave-flash" width="14" height="15" src="http://heisetoufa.javaeye.com/javascripts/syntaxhighlighter/clipboard_new.swf" pluginspage="http://www.macromedia.com/go/getflashplayer" allowscriptaccess="always" quality="high" flashvars="clipboard=import%20java.util.regex.Matcher%3B%0Aimport%20java.util.regex.Pattern%3Bpublic%20class%20Test%20%7B%0A%0A%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%20%20%20%20%20%20%20%20String%20str%20%3D%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22%3Ctable%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5Cn%22%20%2B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22%20%20%3Ctr%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5Cn%22%20%2B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22%20%20%20%20%3Ctd%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5Cn%22%20%2B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22%20%20%20%20%20%20%20Hello%20World!%20%20%20%20%5Cn%22%20%2B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22%20%20%20%20%3C%2Ftd%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5Cn%22%20%2B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22%20%20%3C%2Ftr%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5Cn%22%20%2B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22%3C%2Ftable%3E%22%3B%0A%20%20%20%20%20%20%20%20String%20regex%20%3D%20%22%3Ctd%3E(.%2B%3F)%3C%2Ftd%3E%22%3B%0A%20%20%20%20%20%20%20%20Pattern%20pattern%20%3D%20Pattern.compile(regex)%3B%0A%20%20%20%20%20%20%20%20Matcher%20matcher%20%3D%20pattern.matcher(str)%3B%0A%20%20%20%20%20%20%20%20while(matcher.find())%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(matcher.group(1).trim())%3B%0A%20%20%20%20%20%20%20%20%7D%20%20%20%20%20%20%20%20%0A%20%20%20%20%7D%0A%7D%0A%0A">
    1. import java.util.regex.Matcher;  
    2. import java.util.regex.Pattern;public class Test {  
    3.   
    4.     public static void main(String[] args) {  
    5.         String str =   
    6.                 "<table>                \n" +  
    7.                 "  <tr>                 \n" +  
    8.                 "    <td>               \n" +  
    9.                 "       Hello World!    \n" +  
    10.                 "    </td>              \n" +  
    11.                 "  </tr>                \n" +  
    12.                 "</table>";  
    13.         String regex = "<td>(.+?)</td>";  
    14.         Pattern pattern = Pattern.compile(regex);  
    15.         Matcher matcher = pattern.matcher(str);  
    16.         while(matcher.find()) {  
    17.             System.out.println(matcher.group(1).trim());  
    18.         }          
    19.     }  
    20. }  
     

    上面这个是不能从 str 抽取出东西的,因为 td 的后面带有换行符,我们只要更改一下: 

    Pattern pattern = Pattern.compile(regex, Pattern.DOTALL); 

    这样就行了,如果 td 还得不区分大小写的话,再改成:

    Pattern pattern = Pattern.compile(regex, Pattern.DOTALL | Pattern.CASE_INSENSITIVE);

    这样的话,td 哪怕是大写的这个表达式都能把 td 之间的字符区抽取出来。 

    当然和 Pattern.CASE_INSENSITIVE 一样,Pattern.DOTALL 也有内嵌标志表达式,即 (?s) 
    s 的意思表示 single-line 就是忽略换行符什么的,只看成单行进行处理。 

    这个表达式使用内嵌 (?s) 的话可以改为:

    String regex = "(?s)<td>(.+?)</td>";

    如果还要不区分大小写的话,再加上 i 标志:
    String regex 
    = "(?s)(?i)<td>(.+?)</td>";

    但这样显得很拖沓,可以把它们合并起来:
    String regex 
    = "(?is)<td>(.+?)</td>";    // 秩序无所谓

    最后需要说明一下的是,我曾看到过由于不明白 DOTALL,为了让 . 匹配行结束符,直接把表达式写成:

    String regex = "<td>((.|\\s)+?)</td>";

    这样做是极其危险的,由于选择结构的匹配效率问题,这样做在比较长的字符串时会造成堆栈溢出, 
    使程序崩溃,如果使用 DOTALL 或者 (?s) 的话就不会出现这种情况。

    2:不以某某开头 ,比如不以www开头 

    Java代码 < type="application/x-shockwave-flash" width="14" height="15" src="http://heisetoufa.javaeye.com/javascripts/syntaxhighlighter/clipboard_new.swf" pluginspage="http://www.macromedia.com/go/getflashplayer" allowscriptaccess="always" quality="high" flashvars="clipboard=public%20class%20Test%20%7B%0A%0A%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%20%20%20%20%20%20%20%20String%5B%5D%20strs%20%3D%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22abc1232%22%2C%20%20%22wwwadsf%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22awwwfas%22%2C%20%20%22wwadfsf%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22%22%2C%20%22ww%22%2C%20%22%20%22%2C%20%22www%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%3B%0A%20%20%20%20%20%20%20%20String%20regex%20%3D%20%22(%3F%3A(%3F!%5Ewww).)*%22%3B%0A%20%20%20%20%20%20%20%20for(String%20str%20%3A%20strs)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20System.out.printf(%22%25-7s%20%25s%25n%22%2C%20str%2C%20str.matches(regex))%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%7D%0A">
    1. public class Test {  
    2.   
    3.     public static void main(String[] args) {  
    4.         String[] strs = {  
    5.                 "abc1232",  "wwwadsf",  
    6.                 "awwwfas",  "wwadfsf",  
    7.                 "", "ww", " ", "www"  
    8.             };  
    9.         String regex = "(?:(?!^www).)*";  
    10.         for(String str : strs) {  
    11.             System.out.printf("%-7s %s%n", str, str.matches(regex));  
    12.         }  
    13.     }  
    14. }  

    (?!X) 专业名称为 Negative Lookahead,表示字符间缝隙后面不允许出现的字符, 
    即匹配字符间的缝隙,如果缝隙后的字符不是 X 的话,那这个缝隙就匹配成功。 

    举个例子,aab 和 aac,现有表达式 aa(?!b) 这时我们能匹配到的字符串是 aac, 
    因为 aa 的后面的缝隙之后不允许出现字符 b,因此只有 aac 进行了匹配。 

    再来看个示例: 

    Java代码 < type="application/x-shockwave-flash" width="14" height="15" src="http://heisetoufa.javaeye.com/javascripts/syntaxhighlighter/clipboard_new.swf" pluginspage="http://www.macromedia.com/go/getflashplayer" allowscriptaccess="always" quality="high" flashvars="clipboard=public%20class%20Test%20%7B%0A%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%20%20%20%20%20%20%20%20String%20str%20%3D%20%22AQuickBrownFoxJumpsOverTheLazyDog%22%3B%0A%20%20%20%20%20%20%20%20String%5B%5D%20strs%20%3D%20str.split(%22(%3F%3C!%5E)(%3F%3D%5BA-Z%5D)%22)%3B%0A%20%20%20%20%20%20%20%20for(String%20s%20%3A%20strs)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(s)%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%7D%0A">
    1. public class Test {  
    2.     public static void main(String[] args) {  
    3.         String str = "AQuickBrownFoxJumpsOverTheLazyDog";  
    4.         String[] strs = str.split("(?<!^)(?=[A-Z])");  
    5.         for(String s : strs) {  
    6.             System.out.println(s);  
    7.         }  
    8.     }  
    9. }  

    根据大写字母拆分字符串。当然了,这个使用字符串进行分析同样也能进行拆分, 
    但是使用正则表达式来拆的话更为便捷直观一些。 

    在进行这种拆分时,由于在拆分后的字符数不能减少,因此只能使用零宽度的 
    lookaround 功能进行匹配,lookaround 包括四个,即:

    (?=X)  (?!X)  (?<=X)  (?<!X)

    来看一下这个表达式:(? <!^)(?=[A-Z]) 

    前面说到过 (?!) 表示缝隙后面不允许出现的东西,而 (? <!) 表示缝隙前不允许出现的东西。 
    (?=) 表示缝隙后允许出现的东西,(? <=) 表示缝隙前允许出现的东西。 

    这个表达式在拆分时,根据零宽度匹配缝隙进行拆分的,这个缝隙必须满足以下条件: 

    (? <!^) 表示缝隙不允许前不能是行开始,即缝隙不能出现在首字母的前面。 
    (?=[A-Z]) 表示缝隙后面允许出现 A-Z 的大写字母。 

    这时这个表达式就匹配了下面带有 ¦ 的缝隙:

    A|Quick|Brown|Fox|Jumps|Over|The|Lazy|Dog
    PS:不加 (
    ?<!^) 的话,会变成:
    |A|Quick|Brown|Fox|Jumps|Over|The|Lazy|Dog

    根据 split 的功能,正则表达式处理程序就根据上面的 ¦ 将字符串给拆分开来了。 


    3,不区分大小写 
    不加任何限制的匹配是匹配分大小写的,但是正则表达式中可以进行改变, 
    有两种方式:参数式和内嵌式。 

    来看个示例:

    Java代码 < type="application/x-shockwave-flash" width="14" height="15" src="http://heisetoufa.javaeye.com/javascripts/syntaxhighlighter/clipboard_new.swf" pluginspage="http://www.macromedia.com/go/getflashplayer" allowscriptaccess="always" quality="high" flashvars="clipboard=import%20java.util.regex.Matcher%3B%0Aimport%20java.util.regex.Pattern%3Bpublic%20class%20Test%20%7B%0A%0A%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20%7B%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20String%20str%20%3D%20%22Book%22%3B%0A%20%20%20%20%20%20%20%20Pattern%20pattern%20%3D%20Pattern.compile(%22book%22)%3B%0A%20%20%20%20%20%20%20%20Matcher%20matcher%20%3D%20pattern.matcher(str)%3B%0A%20%20%20%20%20%20%20%20System.out.println(matcher.matches())%3B%0A%20%20%20%20%7D%0A%7D%0A%0A">
    1. import java.util.regex.Matcher;  
    2. import java.util.regex.Pattern;public class Test {  
    3.   
    4.     public static void main(String[] args) {          
    5.         String str = "Book";  
    6.         Pattern pattern = Pattern.compile("book");  
    7.         Matcher matcher = pattern.matcher(str);  
    8.         System.out.println(matcher.matches());  
    9.     }  
    10. }  
     

    上面的这个表达式 book 是不能匹配字符串 Book 的,这时我们只要给定编译时的参数就可以了: 

    Pattern pattern = Pattern.compile("book", Pattern.CASE_INSENSITIVE); 

    Pattern.CASE_INSENSITIVE 这是一个 int 类型的常量,值为 2。表示表达式忽略大小写进行区配。 

    如果我们不采用 Pattern 和 Matcher 两个类来匹配的话,只是使用 String 的 matches 方法的话, 
    我们就不能指定表达式的编译参数了,这时就需要采用内嵌标志表达式了,与 Pattern.CASE_INSENSITIVE 
    对应的内嵌标志表达式是 (?i),它有四种形式: 
    1,(?i) 
    2,(?-i) 
    3,(?i:X) 
    4,(?-i:X) 
    不带有 - 的是开标志,带有 - 的是关标志。 

    把上面的代码改成这样:

    Java代码 < type="application/x-shockwave-flash" width="14" height="15" src="http://heisetoufa.javaeye.com/javascripts/syntaxhighlighter/clipboard_new.swf" pluginspage="http://www.macromedia.com/go/getflashplayer" allowscriptaccess="always" quality="high" flashvars="clipboard=public%20class%20Test%20%7B%0A%0A%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20%7B%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20String%20str%20%3D%20%22Book%22%3B%0A%20%20%20%20%20%20%20%20String%20regex%20%3D%20%22(%3Fi)book%22%3B%0A%20%20%20%20%20%20%20%20System.out.println(str.matches(regex))%3B%0A%20%20%20%20%7D%0A%7D%0A%0A">
    1. public class Test {  
    2.   
    3.     public static void main(String[] args) {          
    4.         String str = "Book";  
    5.         String regex = "(?i)book";  
    6.         System.out.println(str.matches(regex));  
    7.     }  
    8. }  

    我们就达到了同样的效果,当然这样并不是最好的,因为字符串中只有 B 是大写的, 
    我们没有必要把所有的字符都进行不区分大小写匹配,我们可以在打开标志,用 (?i) 的 
    第二种形式马上关掉它: 
        String regex = "(?i)b(?-i)ook"; 

    这样的话,只有 b 是区分大小写了,而 (?-i) 后面的还是得区分大小写匹配的。这样写 
    可能看上去很不顺眼,我们还能使用第 3 种形式直接指定某些字符是不区分大小写的。 
        String regex = "(?i:b)ook"; 

    这样的表达式与上面的那个在语义上是相同的。就效率上肯定是优于一下子开,一下子关的。 

    可见内嵌标志表达式要比指定编译参数的功能强大许多。 

    使用建议:如果能确定某些字符的大小写时,尽量使用已确定的字符,对于不确定的可以采用 
    (?i:X) 的方式指定。因此打开不区分大小写开关时,对匹配的性能是有一定影响的。 

    思考一下:String regex = "(?i)b(?-i:oo)k"; 这个表达式的意思? 


    另外:第 1 和第 4,我没看明白需要了解什么,请在下面的楼层中具体地说明一下。

    4:2个单元的或操作 

    ¦ 称为多选结构,用于匹配 ¦ 之中的任何一个,拿你的例子来说明:

    Java代码 < type="application/x-shockwave-flash" width="14" height="15" src="http://heisetoufa.javaeye.com/javascripts/syntaxhighlighter/clipboard_new.swf" pluginspage="http://www.macromedia.com/go/getflashplayer" allowscriptaccess="always" quality="high" flashvars="clipboard=import%20java.util.regex.Matcher%3B%0Aimport%20java.util.regex.Pattern%3Bpublic%20class%20Test%20%7B%0A%0A%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%20%20%20%20%20%20%20%20String%20str%20%3D%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22%3Cimg%20src%3D%5C%22http%3A%2F%2Fwww.google.com%2F1.gif%5C%22%2F%3E%5Cn%22%20%2B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22%3Cimg%20src%3D%5C%22http%3A%2F%2F3w.google.com%2F1.gif%5C%22%2F%3E%5Cn%22%20%2B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22%3Cimg%20src%3D%5C%22http%3A%2F%2Fabc.baidu.com%2F1.gif%5C%22%2F%3E%22%3B%0A%20%20%20%20%20%20%20%20String%20regex%20%3D%20%22%3Cimg%5C%5Cssrc%3D%5C%22http%3A%2F%2F(%3F%3Aww%7C3)w.google.com%2F1.gif%5C%22%2F%3E%22%3B%0A%20%20%20%20%20%20%20%20Pattern%20pattern%20%3D%20Pattern.compile(regex)%3B%0A%20%20%20%20%20%20%20%20Matcher%20matcher%20%3D%20pattern.matcher(str)%3B%0A%20%20%20%20%20%20%20%20while(matcher.find())%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20System.out.println(matcher.group())%3B%0A%20%20%20%20%20%20%20%20%7D%20%20%20%20%20%20%20%20%0A%20%20%20%20%7D%0A%7D%0A%0A">
    1. import java.util.regex.Matcher;  
    2. import java.util.regex.Pattern;public class Test {  
    3.   
    4.     public static void main(String[] args) {  
    5.         String str =   
    6.                 "<img src=\"http://www.google.com/1.gif\"/>\n" +  
    7.                 "<img src=\"http://3w.google.com/1.gif\"/>\n" +  
    8.                 "<img src=\"http://abc.baidu.com/1.gif\"/>";  
    9.         String regex = "<img\\ssrc=\"http://(?:ww|3)w.google.com/1.gif\"/>";  
    10.         Pattern pattern = Pattern.compile(regex);  
    11.         Matcher matcher = pattern.matcher(str);  
    12.         while(matcher.find()) {  
    13.             System.out.println(matcher.group());  
    14.         }          
    15.     }  
    16. }  
     

    注意到其中的 (?:ww ¦3) 在进行多选匹配时尽量找出多选中的规律,以减少多选的字符, 
    www 和 3w 在最后一个字符可以共用,前面的不一样。 

    (?: ) 的意思表示组成一组,如果没有 (?: ) 这样的话,表达式就变成了:

    String regex = "<img\\ssrc=\"http://ww|3w.google.com/1.gif\"/>";

    这样的语义完全变掉了, ¦ 是在一组中进行选择,由于上面的那个表达式中没有组,就把整个表 
    达式作为了一组,使用 ¦ 的话,就进行了整个表达式的多选结构了。这个表达式的意思是: 
    匹配 <img ssrc="http://ww 或者是 3w.google.com/1.gif"/>,这样的结果并不是我们所要的。 

    我们仅仅需要在 ww 和 3 之间进行选择,这时只要把 ww 和 3 放在一组中进行多选择就可以了, 
    变成 (?:ww ¦3)。 

    还有,在多选结构中尽量把出现频率高的放在前面,这样可以加快匹配速度。 

    多选结构的效率在传统型的引擎中是效率低下的,如果是单个字符的选择,比如 a $ & 之中的一个, 
    那就不要使用 (?:a ¦$ ¦&) 了,可以直接使用字符类 [a$&] 就可以了。

    5:split分割字母和数字,简单正则缝隙

    Java代码 < type="application/x-shockwave-flash" width="14" height="15" src="http://heisetoufa.javaeye.com/javascripts/syntaxhighlighter/clipboard_new.swf" pluginspage="http://www.macromedia.com/go/getflashplayer" allowscriptaccess="always" quality="high" flashvars="clipboard=public%20class%20Test01%20%7B%0A%20%20%20%20public%20static%20void%20main(String%5B%5D%20args)%20%7B%0A%20%20%20%20%20%20%20%20String%20str%20%3D%20%22one123%22%3B%0A%20%20%20%20%20%20%20%20String%20regex%20%3D%20%22(%3F%3C%3Done)(%3F%3D123)%22%3B%0A%20%20%20%20%20%20%20%20String%5B%5D%20strs%20%3D%20str.split(regex)%3B%0A%20%20%20%20%20%20%20%20for(int%20i%20%3D%200%3B%20i%20%3C%20strs.length%3B%20i%2B%2B)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20System.out.printf(%22strs%5B%25d%5D%20%3D%20%25s%25n%22%2C%20i%2C%20strs%5Bi%5D)%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%7D%0A%0A">
    1. public class Test01 {  
    2.     public static void main(String[] args) {  
    3.         String str = "one123";  
    4.         String regex = "(?<=one)(?=123)";  
    5.         String[] strs = str.split(regex);  
    6.         for(int i = 0; i < strs.length; i++) {  
    7.             System.out.printf("strs[%d] = %s%n", i, strs[i]);  
    8.         }  
    9.     }  
    10. }
  • 相关阅读:
    字符编码总结
    文件操作总结(2)
    Codeforces Round #432 (Div. 2, based on IndiaHacks Final Round 2017) C. Five Dimensional Points 暴力
    UVA 10048
    UVA 247
    UVA 1151
    UVA 1395
    Codeforces Round #260 (Div. 1) D. Serega and Fun 分块
    Codeforces Beta Round #13 E. Holes 分块
    Codeforces Round #404 (Div. 2) E. Anton and Permutation 分块
  • 原文地址:https://www.cnblogs.com/Memory/p/2023737.html
Copyright © 2011-2022 走看看