正则表达式中Greedy、Reluctant、Possessive数量词的区别

首先看一下API文档里的定义:
这里写图片描述

再从字面意义上看:
Greedy —-贪婪的
Reluctant —-勉强的,不情愿的
Possessive—-所有的,所有格的

Greedy 数量词(贪婪的)
它的匹配方式是先把整个字符串吞下,然后匹配整个字符串,如果不匹配,就从右端吐出一个字符,再进行匹配,直到找到匹配或把整个字符串吐完为止。

Reluctant 数量词(勉强的,不情愿的)
它先从最小匹配开始,先从左端吞入一个字符,然后进行匹配,若不匹配就再吞入一个字符,直到找到匹配或将整个字符串吞入为止。

Possessive 数量词(所有的,所有格的)
直接匹配整个字符串,如果完全匹配就匹配成功,否则匹配失败。效果相当于equals()。

2015年搜狗Java工程师笔试题:
这里写图片描述

正则表达式中:(?=X) X,通过零宽度的正 lookahead,即下一个符号为X。“(?=\()”,即表示下一个字符为’(‘。

使用Greedy 数量词进行匹配:

public class RegexTest
{
    public static void main(String[] args)
    {
        String str = "北京市(海淀区)(朝阳区)(西城区)";
        String Greedy_regex = ".*(?=\\()";
        Pattern pattern = Pattern.compile(Greedy_regex);
        Matcher matcher = pattern.matcher(str);
        String subString = null;
        if(matcher.find())
        {
            subString = matcher.group();
            System.out.println(subString);
        }
    }
}
//打印结果为:北京市(海淀区)(朝阳区)

使用Reluctant 数量词进行匹配:

public class RegexTest
{
    public static void main(String[] args)
    {
        String str = "北京市(海淀区)(朝阳区)(西城区)";
        String Reluctant_regex = ".*?(?=\\()";
        Pattern pattern = Pattern.compile(Reluctant_regex);
        Matcher matcher = pattern.matcher(str);
        String subString = null;
        if(matcher.find())
        {
            subString = matcher.group();
            System.out.println(subString);
        }
    }
}
//打印结果为:北京市

使用Possessive 数量词进行匹配:

public class RegexTest
{
    public static void main(String[] args)
    {
        String str = "北京市(海淀区)(朝阳区)(西城区)";
        String Possessive_regex = ".*+(?=\\()";
        Pattern pattern = Pattern.compile(Possessive_regex);
        Matcher matcher = pattern.matcher(str);
        String subString = null;
        if(matcher.find())
        {
            subString = matcher.group();
            System.out.println(subString);
        }
    }
}
//打印结果为:空

这道笔试题的要求是:截取字符串中第一个出现的英文左括号之前的字符串。
Greedy 数量词是先匹配整个字符串,然后依次去掉最右端的一个字符再进行匹配,所以结果为:北京市(海淀区)(朝阳区)。
Reluctant 数量词是从最左边一个字符开始匹配,不匹配就再吞入一个字符,直到找到匹配或将整个字符串吞入为止,所以这个符合题意。
Possessive 数量词是直接匹配整个字符串,如果完全匹配就匹配成功,否则匹配失败,所以匹配不成功,也就没有返回值。

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
前言:本资源来自于javaeye,原资源链接地址:http://www.javaeye.com/topic/67398 原文如下: 以前写了一个java的正规表达式的java工具类,分享一下,有用到的欢迎下载使用。 如果你有常用的定义好的,且测试通过的正规表达式,欢迎跟贴,也让我享用一下 . 类用到了 jakarta-oro-2.0.jar 包,请大家自己在 apache网站下下载 在这是junit测试单元类我就不提交了,在main()方法有几个小测试,有兴趣自己玩吧. 这个工具类目前主要有25种正规表达式(有些不常用,但那时才仔细深入的研究了一下正规,写上瘾了,就当时能想到的都写了): 1.匹配图象; 2 匹配email地址; 3 匹配匹配并提取url ; 4 匹配并提取http ; 5.匹配日期 6 匹配电话; 7 匹配身份证 8 匹配邮编代码 9. 不包括特殊字符的匹配 (字符串不包括符号 数学次方号^ 单引号' 双引号" 分号; 逗号, 帽号: 数学减号- 右尖括号> 左尖括号 0) 12 匹配正整数 13 匹配非正整数(负整数 + 0) 14 匹配负整数; 15. 匹配整数 ; 16 匹配非负浮点数(正浮点数 + 0) 17. 匹配正浮点数 18 匹配非正浮点数(负浮点数 + 0) 19 匹配负浮点数; 20 .匹配浮点数; 21. 匹配由26个英文字母组成的字符串; 22. 匹配由26个英文字母的大写组成的字符串 23 匹配由26个英文字母的小写组成的字符串 24 匹配由数字和26个英文字母组成的字符串; 25 匹配由数字、26个英文字母或者下划线组成的字符串; java源码: /* * Created on 2005-4-15 * * Summary of regular-expression constructs 正则表达式结构简介: * Construct Matches * Characters 字符: * x The character x x 字符 x * \\ The backslash character \\ 反斜杠 * \0n The character with octal value 0n (0 <= n <= 7) \0n 十进制数 (0 <= n <= 7) * \0nn The character with octal value 0nn (0 <= n <= 7) \0nn 十进制数 0nn (0 <= n <= 7) * \0mnn The character with octal value 0mnn (0 <= m <= 3, 0 <= n <= 7) \0mnn 十进制数 0mnn (0 <= m <= 3, 0 <= n <= 7) * \xhh The character with hexadecimal value 0xhh \xhh 十六进制数 0x
正则表达式的灾难性回溯指的是当一个正则表达式在匹配某个字符串时,由于某些模式的匹配方式导致了非常高的时间复杂度,甚至可能导致程序崩溃或出现死循环的情况。 回溯是指正则表达式引擎在尝试匹配一个字符串时,如果当前的匹配不成功,会自动回退到前一个位置尝试其他的匹配方式。在某些情况下,特别是对于复杂的正则表达式和长字符串,回溯操作可能会导致非常高的时间复杂度。 灾难性回溯往往发生在正则表达式存在大量的重复或可选项,并且这些可选项有多种组合方式时。例如,当使用连续多个重复字符(比如 "a{1,100}")或者使用多层嵌套的可选项(比如 "(a|a)*")时,回溯操作会变得非常耗时。 为了避免灾难性回溯,可以通过以下几种方式来优化正则表达式的性能: 1. 尽量避免使用过于复杂的正则表达式,特别是大量的重复或可选项。 2. 使用惰性匹配(non-greedy matching)来限制匹配的范围,比如使用"*?"、"+?"或"??"等操作符。 3. 使用具体的字符或字符类来替代通用的匹配模式,尽量减少回溯的可能性。 4. 对于已知的输入范围,可以使用定位符(anchors)来限定匹配的位置,比如使用"^"和"$"来限定开头和结尾。 总之,合理地使用正则表达式,并避免出现灾难性回溯的情况,可以提高正则表达式的执行效率和稳定性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值