`
gk23
  • 浏览: 177157 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

正则表达式经验总结一

阅读更多

文章出处: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代码 复制代码
  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. }  
import java.util.regex.Matcher;
import java.util.regex.Pattern;public class Test {

    public static void main(String[] args) {
        String str = 
                "<table>                \n" +
                "  <tr>                 \n" +
                "    <td>               \n" +
                "       Hello World!    \n" +
                "    </td>              \n" +
                "  </tr>                \n" +
                "</table>";
        String regex = "<td>(.+?)</td>";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(str);
        while(matcher.find()) {
            System.out.println(matcher.group(1).trim());
        }        
    }
}

 

 

 

 

 

上面这个是不能从 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代码 复制代码
  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. }  
public class Test {

    public static void main(String[] args) {
        String[] strs = {
                "abc1232",  "wwwadsf",
                "awwwfas",  "wwadfsf",
                "", "ww", " ", "www"
            };
        String regex = "(?:(?!^www).)*";
        for(String str : strs) {
            System.out.printf("%-7s %s%n", str, str.matches(regex));
        }
    }
}

 

 

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

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

再来看个示例:

Java代码 复制代码
  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. }  
public class Test {
    public static void main(String[] args) {
        String str = "AQuickBrownFoxJumpsOverTheLazyDog";
        String[] strs = str.split("(?<!^)(?=[A-Z])");
        for(String s : strs) {
            System.out.println(s);
        }
    }
}

 

 

 

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

在进行这种拆分时,由于在拆分后的字符数不能减少,因此只能使用零宽度的
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代码 复制代码
  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. }  
import java.util.regex.Matcher;
import java.util.regex.Pattern;public class Test {

    public static void main(String[] args) {        
        String str = "Book";
        Pattern pattern = Pattern.compile("book");
        Matcher matcher = pattern.matcher(str);
        System.out.println(matcher.matches());
    }
}

 

 

 

 

 

 

 

 

 

上面的这个表达式 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代码 复制代码
  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. }  
public class Test {

    public static void main(String[] args) {        
        String str = "Book";
        String regex = "(?i)book";
        System.out.println(str.matches(regex));
    }
}

 

 

 

我们就达到了同样的效果,当然这样并不是最好的,因为字符串中只有 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代码 复制代码
  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. }  
import java.util.regex.Matcher;
import java.util.regex.Pattern;public class Test {

    public static void main(String[] args) {
        String str = 
                "<img src=\"http://www.google.com/1.gif\"/>\n" +
                "<img src=\"http://3w.google.com/1.gif\"/>\n" +
                "<img src=\"http://abc.baidu.com/1.gif\"/>";
        String regex = "<img\\ssrc=\"http://(?:ww|3)w.google.com/1.gif\"/>";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(str);
        while(matcher.find()) {
            System.out.println(matcher.group());
        }        
    }
}

 

 

 

 

 

 

 

注意到其中的 (?: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代码 复制代码
  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. }  
public class Test01 {
    public static void main(String[] args) {
        String str = "one123";
        String regex = "(?<=one)(?=123)";
        String[] strs = str.split(regex);
        for(int i = 0; i < strs.length; i++) {
            System.out.printf("strs[%d] = %s%n", i, strs[i]);
        }
    }
}

 

分享到:
评论

相关推荐

    Java使用正则表达式提取XML节点内容的方法示例

    为了帮助开发者更好地掌握Java正则表达式技术,我们提供了一系列的Java正则表达式技巧大全,包括《Java正则表达式技巧大全》、《Java数据结构与算法教程》、《Java操作DOM节点技巧总结》、《Java文件与目录操作技巧...

    正则表达式应用总结

    本文结合多年使用正则表达式的实践经验,深入浅出地介绍了正则表达式的基本概念、Java中的特殊处理方式以及一些典型的使用场景。掌握正则表达式可以帮助我们高效地处理文本数据,是每个程序员必备的技能之一。希望...

    Apache重写与正则表达式经验总结

    正则表达式则是实现URL重写的基石,它是一种强大的文本匹配模式,能够帮助我们精确地识别和操作URL。 首先,我们需要理解.htaccess文件。这是Apache服务器中的一个配置文件,用于控制网站的目录级配置,如重写规则...

    精通正则表达式中文版英文版_中文版为扫描版

    在正则表达式的世界里,基础概念包括字符类(如匹配任何数字[\d])、量词(匹配0次或多次*,1次或多次+,至少n次{n}等)、分组与捕获(使用括号()来定义一个子模式)、预查(用^符号否定预查,如[^abc]匹配非abc的...

    常用正则表达式(经验积累)

    根据提供的标题、描述以及部分内文,我们可以整理出一系列与正则表达式相关的知识点,这些知识点主要涵盖了在软件开发过程中常见的验证和匹配需求。 ### 常用正则表达式 #### 1. 匹配中文字符 **正则表达式**: `[\...

    C# 正则表达式总结_V2

    在"C# 正则表达式总结_V2"中,应包含了一系列的测试用例,这些用例涵盖了上述各个知识点,包括各种正则表达式的编写、使用`Regex`类的方法进行匹配、替换和分割操作等。通过运行这些代码,开发者可以更直观地理解...

    精通正则表达式电子书

    1. **数据验证**:利用正则表达式进行表单输入的有效性验证。 2. **文本搜索**:在大型文档中查找特定模式或关键词。 3. **格式转换**:将一种格式的数据转换为另一种格式,例如日期格式转换。 4. **错误检测**:...

    清华大学精品Python学习PPT课件-第5章 Python正则表达式.pptx

    第五章“字符串与正则表达式”深入探讨了这一关键主题,旨在帮助初学者和有经验的开发者更好地理解和使用字符串及正则表达式。 **5.1 字符串基础** 1. **字符串表示**:Python中的字符串可以由单引号或双引号包围...

    正则表达式教程 正则表达式 教程 独家总结

    正则表达式是一种强大的文本处理工具,它允许程序员或用户用简洁的模式来描述字符串的复杂匹配规则。正则表达式的主要用途是进行文本匹配,即在给定的字符串中寻找符合特定模式的子串。相对于简单的通配符(如*和?)...

    正则表达式测试器

    总结来说,“正则表达式测试器”是一个实用的开发工具,尤其适合于对正则表达式不太熟悉的程序员。通过它,用户可以直观地看到正则表达式的匹配效果,从而更好地理解和优化自己的正则表达式。同时,该测试器的实现也...

    正则表达式之道.doc

    《正则表达式之道》一书由Steve Mansour撰写,Neo Lee翻译,内容涵盖了正则表达式的各个方面,适合初学者及有一定经验的开发者阅读。 #### 二、正则表达式示例 书中提供了不同难度级别的正则表达式示例,帮助读者...

    正则表达式之道

    ### 正则表达式之道:深入解析与应用 正则表达式是一种强大的文本处理工具,其功能在于通过预设的模式来匹配、查找、替换文本中的字符串。...随着实践经验的积累,你会逐渐发现正则表达式的魅力所在。

    正则表达式语法总结.zip

    本资源“正则表达式语法总结.zip”包含了一个关于正则表达式的详细总结,以及可能的示例图片“孔子1.jpg”,和一个名为“RegExp-master”的可能包含更多相关代码或实例的文件夹。 一、正则表达式基本语法 1. **...

    Net开发辅助 正则表达式分析器 v1.0.7013.19149

    1. **正则表达式测试**:此工具提供了一个友好的界面,开发者可以输入待测试的正则表达式,并在指定的文本上进行匹配操作。这有助于快速验证正则表达式的正确性,避免在代码运行时出现错误。 2. **部分执行**:一个...

    快速完全精通正则表达式

    ##### 如果你已经有一些正则表达式经验 如果你已经对正则表达式有所了解,本书将帮助你进一步扩展知识边界,学习更高级的技术和技巧。 ##### 使用egrep搜索文本文件 egrep是Linux下用于文本搜索的强大工具之一。...

    精通正则表达式~~~

    方法1:依据经验构建正则表达式... 262 真正的“消除循环”解法... 264 方法2:自顶向下的视角... 266 方法3:匹配主机名... 267 观察... 268 使用固化分组和占有优先量词... 268 简单的消除循环的例子... ...

    正则表达式参考手册(英文)

    该手册不仅为正则表达式的初学者提供了入门指导,也为有经验的用户提供了详细的参考。通过理解这些基本的元字符和构造,用户可以构建复杂的正则表达式来进行文本处理和数据提取任务。此外,了解不同的匹配模式(如...

    .net正则表达式测试工具

    1. **模式匹配**:正则表达式由一系列字符和特殊符号组成,用于定义一个模式,用于在文本中查找匹配该模式的字符串。 2. **基本元素**:包括普通字符(如a-z)、元字符(如.、^、$、*、+、?等)和括号等,它们共同...

    正则表达式的具体介绍.docx

    虽然初学者可能会觉得正则表达式有些难以理解,但随着实践经验的积累,将会发现它带来的便利性与效率提升是其他工具难以比拟的。因此,对于任何从事计算机相关工作的人员来说,掌握正则表达式都是非常有价值的技能之...

    正则表达式系统教程(各种编程语言都有)

    5. 不断实践和总结,积累经验,逐步成为正则表达式专家。 记住,正则表达式虽然强大,但并不易学,需要时间和耐心。通过这个系统的教程,你将逐步掌握这个强大的工具,并能在各种项目中发挥它的威力。祝你在学习...

Global site tag (gtag.js) - Google Analytics