加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

正则表达式(多行匹配,不以某某开头,不区分大小写,2个单元的或

发布时间:2020-12-14 01:24:21 所属栏目:百科 来源:网络整理
导读:文章出处:http://topic.csdn.net/u/20080627/14/8a91b33a-f35c-4303-85b5-e0a8da462202.html 1 多行匹配 2 不以某某开头 ,比如不以www开头 3 不区分大小写 4 2个单元的或操作,比如 www | 3w 都可以这种 火龙果 回答: 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. importjava.util.regex.Matcher;
  2. importjava.util.regex.Pattern;publicclassTest{
  3. staticvoidmain(String[]args){
  4. Stringstr=
  5. "<table>n"+
  6. "<tr>n"+
  7. "<td>n"+
  8. "HelloWorld!n"+
  9. "</td>n"+
  10. "</tr>n"+
  11. "</table>";
  12. Stringregex="<td>(.+?)</td>";
  13. Patternpattern=Pattern.compile(regex);
  14. Matchermatcher=pattern.matcher(str);
  15. while(matcher.find()){
  16. System.out.println(matcher.group(1).trim());
  17. }
  18. }

上面这个是不能从 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开头
String[]strs={

  • "abc1232","wwwadsf",
  • "awwwfas","wwadfsf",250)"> "","ww","","www"
  • };
  • Stringregex="(?:(?!^www).)*";
  • for(Stringstr:strs){
  • System.out.printf("%-7s%s%n",str,str.matches(regex));
  • (?!X) 专业名称为 Negative Lookahead,表示字符间缝隙后面不允许出现的字符,
    即匹配字符间的缝隙,如果缝隙后的字符不是 X 的话,那这个缝隙就匹配成功。

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

    再来看个示例:
    Stringstr="AQuickBrownFoxJumpsOverTheLazyDog";
  • String[]strs=str.split("(?<!^)(?=[A-Z])");
  • for(Strings: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,不区分大小写
    不加任何限制的匹配是匹配分大小写的,但是正则表达式中可以进行改变,
    有两种方式:参数式和内嵌式。

    来看个示例:

    Stringstr="Book";

  • Patternpattern=Pattern.compile("book");
  • 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)
    不带有 - 的是开标志,带有 - 的是关标志。

    把上面的代码改成这样:

    Stringregex="(?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个单元的或操作

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

    "<imgsrc="http://www.google.com/1.gif"/>n"+

  • "<imgsrc="http://3w.google.com/1.gif"/>n"+
  • "<imgsrc="http://abc.baidu.com/1.gif"/>";
  • Stringregex="<imgssrc="http://(?:ww|3)w.google.com/1.gif"/>";
  • System.out.println(matcher.group());
  • 注意到其中的 (?:ww |3) 在进行多选匹配时尽量找出多选中的规律,以减少多选的字符,
    www 和 3w 在最后一个字符可以共用,前面的不一样。

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

    String regex="<imgssrc="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分割字母和数字,简单正则缝隙

    classTest01{
  • Stringstr="one123";
  • Stringregex="(?<=one)(?=123)";
  • String[]strs=str.split(regex);
  • for(inti=0;i<strs.length;i++){
  • System.out.printf("strs[%d]=%s%n",i,strs[i]);
  • }
  • (编辑:李大同)

    【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

      推荐文章
        热点阅读