正则中的贪婪匹配 /g

刚看到一个超赞的例子可以很好的解释贪婪匹配的问题。
一个朋友的说:50 万和100 万你要哪个?我说100 万,他笑了笑说,我两个都要!
这不正是正则中的贪婪匹配吗?

示例

有个字符串

var str="《葬花吟》15209275865是清代文学家曹15632365236雪芹的小说《红楼梦》第二十18569853621七回中女主角林黛玉所吟诵的一首古体诗。"

我们需要把这个字符串中的所有的电话号码匹配出来。这里是所有,也就是贪婪匹配了,并不是匹配一个就算了。

贪婪匹配电话的正则如下:

var reg = /[1][3456789][0123456789][0-9]{8}/g;

测试:
在这里插入图片描述
那么非贪婪匹配就只能匹配一个电话了,结果如下:
在这里插入图片描述
虽然只是一个 g 的事,但却失之毫厘,差之千里。

tips

既然这里用到了 match 方法,那么有必要复习一下 exec 方法了。如果我们用 exec 方法实现上面的例子,需要用到 while 循环,因为 exec 虽然返回的也是数组,但是一次只返回一个,没有时返回 null

也就是这样的:
在这里插入图片描述
match 是字符串对象方法 str.match(reg)exec 是正则对象方法 reg.exec(str)

用 while 循环实现:

    var str = "《葬花吟》15209275865是清代文学家曹15632365236雪芹的小说《红楼梦》第二十18569853621七回中女主角林黛玉所吟诵的一首古体诗。"
    var reg = /[1][3456789][0123456789][0-9]{8}/g;

    var arr = reg.exec(str);
    while (arr != null) {
        console.log(arr);
        arr = reg.exec(str);
    }

在这里插入图片描述

<think> 我们正在讨论正则表达式中的贪婪匹配与非贪婪匹配。根据用户的问题,他们想了解这两者的区别和应用场景。结合引用内容,我们可以这样组织回答: 1. 定义贪婪匹配和非贪婪匹配: - 贪婪匹配:尽可能多地匹配字符(默认行为) - 非贪婪匹配:尽可能少地匹配字符(通过添加`?`实现) 2. 对比示例:使用引用[2]中的例子 - 字符串:"abcdefc" - 贪婪模式:`ab.*c` → 匹配整个字符串"abcdefc" - 非贪婪模式:`ab.*?c` → 匹配"abc" 3. 引用[3]的代码示例说明: - 贪婪模式pattern1:`"(.+)(\d+)-(\d+)-(\d+)"` - 匹配整个字符串,其中第一个分组`(.+)`会尽可能多地匹配,导致后面的分组匹配可能不符合预期(例如电话号码部分被拆分) - 非贪婪模式pattern2:`"(.+?)(\d+)-(\d+)-(\d+?)"` - 第一个分组`(.+?)`会匹配到"this is my tel:",然后后面的数字部分被正确分组 4. 引用[1]提到的性能问题:非贪婪模式可能会减少回溯,提高匹配效率。 5. 应用场景: - 贪婪匹配:当需要匹配整个字符串或者直到最后一个分隔符时(例如提取整个HTML文档中的内容)。 - 非贪婪匹配:当需要匹配最短的可能字符串时(例如提取多个标签中的内容,避免跨标签匹配)。 6. 注意事项:非贪婪匹配虽然在某些情况下更精确,但过度使用也可能导致匹配不足(漏掉一些内容),需要根据实际情况选择。 7. 生成相关问题。 现在按照要求组织回答,注意引用标注和格式。 </think> ### 正则表达式中的贪婪匹配与非贪婪匹配 #### 一、核心概念对比 | **特性** | **贪婪匹配** (默认模式) | **非贪婪匹配** (惰性匹配) | |----------------|----------------------------|------------------------------| | **符号表示** | `.*` / `.+` / `.{}` | `.*?` / `.+?` / `.{m,n}?` | | **匹配原则** | 尽可能匹配**最长**的字符串 | 匹配**最短**的满足条件字符串 | | **回溯行为** | 从字符串末尾向前回溯[^1] | 从当前位置向后立即匹配[^2] | | **性能影响** | 高回溯可能导致性能问题[^1] | 回溯较少,通常性能更优 | #### 二、工作流程解析(以`a.*b` vs `a.*?b`为例) **字符串示例:** `aXYbZWaCDb` 1. **贪婪匹配 `a.*b`:** ```mermaid graph LR A[匹配a] --> B[吞并XYbZWaCD] B --> C[回溯查找b] C --> D[找到最后一个b] D --> E[最终匹配aXYbZWaCDb] ``` 2. **非贪婪匹配 `a.*?b`:** ```mermaid graph LR A[匹配a] --> B[尝试匹配b] B -->|失败| C[吞并X] C --> D[尝试匹配b] D -->|失败| E[吞并Y] E --> F[匹配到b] F --> G[结束:匹配aXYb] ``` #### 三、典型场景代码示例 ```python import re text = "<div>内容1</div><div>内容2</div>" # 贪婪匹配匹配整个字符串) greedy = re.search(r'<div>.*</div>', text) print(greedy.group()) # 输出: <div>内容1</div><div>内容2</div> # 非贪婪匹配匹配首个标签) non_greedy = re.search(r'<div>.*?</div>', text) print(non_greedy.group()) # 输出: <div>内容1</div> ``` #### 四、应用场景建议 | **场景** | **推荐模式** | **原因** | |-----------------------------|------------|----------------------------------| | 提取HTML标签内容 | 非贪婪`.*?` | 避免跨标签匹配[^2] | | 匹配完整代码块 | 贪婪`.*` | 需包含嵌套结构 | | 提取属性值(如`src=".*?"`) | 非贪婪`.*?` | 精确获取引号内内容 | | 处理大文本文件 | 非贪婪`.*?` | 减少回溯,提升性能[^1] | #### 五、关键注意事项 1. **换行符处理**: 需用`re.DOTALL`或`(?s)`使`.`匹配换行符 ```python re.findall(r'START.*?END', text, re.DOTALL) # 跨行匹配 ``` 2. **过度匹配防范**: 使用更精确的字符类替代`.` ```regex src="[^"]*?" # 优于 src=".*?" ``` 3. **平衡性能与精度**: - 简单场景:非贪婪模式更安全 - 复杂嵌套:需结合分组和断言 > 引用说明:贪婪模式会持续匹配到最后一个满足条件的字符[^2],而非贪婪模式在首次匹配成功时立即停止[^3]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值