[简单入门]什么是贪婪与非贪婪模式什么是贪婪与非贪婪模式,Go语言简单理解。

jackx 2012-10-17 11:10 | |
对,你理解得对!在正则里,`.*` 默认是 **贪婪模式**,会尽可能多地匹配字符。如果你想让它 **非贪婪**(尽可能少匹配),需要在 `*` 或 `+` 后面加一个 `?`。

---

### 示例

```go
// 原来的贪婪模式
regexp.MustCompile(`^[0-9]+.*-`)

// 非贪婪模式,只匹配到第一个 -
regexp.MustCompile(`^[0-9]+.*?-`)
```

* `.*?` → 匹配任意字符,但尽量少匹配(非贪婪)
* `+?` → 匹配 1 个或多个字符,但尽量少匹配(非贪婪)
* 位置:问号紧跟在 `*` 或 `+` 后面

---

### 对比

```go
s := "12.技术研发中心-数字人智能体V1.4版-"

// 贪婪模式
regexp.MustCompile(`^[0-9]+.*-`).FindString(s)
// 输出: "12.技术研发中心-数字人智能体V1.4版-" (匹配到最后一个 -)

// 非贪婪模式
regexp.MustCompile(`^[0-9]+.*?-`).FindString(s)
// 输出: "12.平台技术中心-" (只匹配第一个 -)
```

所以如果你只想去掉序号前的前缀 `1.平台技术中心-`,用非贪婪模式 `.*?` 就可以了。


```
问题:我是想产如果我有一堆:abcdefabchjkabclmnabc 上面有一堆abc,我想匹配abc到abc时,是匹配一遍就停下,它不贪婪的写法。
```
回复如下:
明白了,你的需求是:在一个字符串中从第一个 `"abc"` 开始匹配到下一个 `"abc"`,**只匹配中间的内容一次,不贪婪地停在第一个符合条件的位置**。

在正则中,可以这样写:

```go
package main

import (
  "fmt"
  "regexp"
)

func main() {
  text := "abcdefabchjkabclmnabc"

  // 非贪婪匹配:从第一个 abc 到下一个 abc
  re := regexp.MustCompile(`abc(.*?)abc`)
  matches := re.FindAllStringSubmatch(text, -1)

  for i, m := range matches {
    fmt.Printf("匹配 %d: %s, 中间内容: %s\n", i+1, m[0], m[1])
  }
}
```

### 解释:

1. `abc` → 匹配开头的 `"abc"`
2. `(.*?)` → 非贪婪模式匹配任意字符(尽量少匹配)
3. `abc` → 匹配结尾的 `"abc"`

### 输出:

```text
匹配 1: abcdefabc, 中间内容: def
匹配 2: abchjkabc, 中间内容: hjk
匹配 3: abclmnabc, 中间内容: lmn
```

✅ 注意关键点:

* `.*?` 就是非贪婪模式,匹配尽量少的字符。
* 贪婪模式 `.*` 会把整个字符串从第一个 `"abc"` 吞到最后一个 `"abc"`,一次匹配结束,不会逐段匹配。



作者:jackx@向东博客 专注WEB应用 构架之美 --- 构架之美,在于尽态极妍 | 应用之美,在于药到病除
地址:http://www.jackxiang.com/post/5668/
版权所有。转载时必须以链接形式注明作者和原始出处及本声明!


最后编辑: jackx 编辑于2025-9-23 17:42
评论列表
发表评论

昵称

网址

电邮

打开HTML 打开UBB 打开表情 隐藏 记住我 [登入] [注册]