# 【Python3.9.13 正则问题】请问\\d+在字符串尾端为何会产生不同的匹配

**URL:** <https://meta.appinn.net/t/topic/43691>\
**Category:** 问题求助\
**Tags:** python, 正则\
**Created:** [2023 年5 月 16 日 05:42 UTC](https://meta.appinn.net/t/topic/43691 "2023-05-16T05:42:07Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

作者： ![highwind](https://meta-edge.appinn.com/user_avatar/meta.appinn.net/highwind/32/2255_2.png) [@highwind](https://meta.appinn.net/u/highwind)\
发布日期： [2023 年5 月 16 日 05:42 UTC](https://meta.appinn.net/t/topic/43691/1 "2023-05-16T05:42:07Z")

</div>

s = “hello123world456www7.89你好001”

**Match1**

```auto

match = re.findall(r'\d+(\D+)', s)

```

`['world', 'www', '.', '你好']`

**Match2**

```auto

match = re.findall(r'\d+(\D+)\d+', s)

```

`['world', '.']`

**Match3**

```auto

match = re.findall(r'\d+(\D+)\d', s)

```

`['world', 'www', '你好']`

请问各位大大为啥 \d+在字符串末尾的时候会产生不同的匹配呀，难道是这个d代表除了0~9之外其他字符吗？谢谢解答哟

---

<div class="post-metadata">

作者： ![Niceb](https://meta-edge.appinn.com/user_avatar/meta.appinn.net/niceb/32/4721_2.png) [@Niceb](https://meta.appinn.net/u/Niceb)\
发布日期： [2023 年5 月 16 日 06:03 UTC](https://meta.appinn.net/t/topic/43691/2 "2023-05-16T06:03:58Z")

</div>

好神奇， 给人的感觉是从前往后匹配的时候， 如果前面匹配到了 那匹配到的字符就不参加后面的匹配了

比如说Match2中， 第一个匹配到的world 完整的匹配应该是“123world456”， 匹配后面的字符串的时候"123world456"被排除了（也就是后续匹配的时候只有“www7.89你好001”参加了匹配），所以没有匹配到“www”这个结果

我说的这个“被排除了”， 可能更合适的表达应该是 下次匹配从“123world456”之后开始进行，所以就没有包括“456”这三个数字，，不知道表达清楚了没有。。。

后面的也是类似的。。

之前用py好像没有关注到类似的情况…

---

<div class="post-metadata">

作者： ![jxcangel](https://meta-edge.appinn.com/user_avatar/meta.appinn.net/jxcangel/32/46962_2.png) [@jxcangel](https://meta.appinn.net/u/jxcangel)\
发布日期： [2023 年5 月 16 日 06:19 UTC](https://meta.appinn.net/t/topic/43691/3 "2023-05-16T06:19:51Z")

</div>

先确定这几个概念：

1. \d+ 表示匹配数字
2. \D+ 表示匹配到非数字字符
3. re.findall 表示返回 s 里所有匹配到括号里的项，也就是非数字的内容

好了，我们来解题：

1. Match1: 必须返回前面有数字，后面是字符的内容。这样第一个 hello 前面没数字，后续 world, www, 你好都有数字在前面，最后一个数字 001 后没有字符，所以返回正确

2. Match2: 必须返回前面有数字，中间是字符，后面还跟着数字的内容。这样第一个 hello 前面没数字但后面有，不正确，world 前面有123，后面又456，所以匹配到，然后 www 因为前面的 456 已经被 world 部分匹配到了，所以算前面没数字，略过，7.89 正好符合前后有数字，中间的点不是数字的情况，匹配到了，再后面的“你好”因为前面的89被点匹配过，即使后面有数字也不满足前面有数字的情况，所以只能抱歉，最终结果是 ‘world’, ‘.’，结果也正确

3. Match3: 前后必须有数字，但最后一个数字因为没有数量标记，所以必须只有1个。我们再来看看：hello 前面没数字，略过，world 前面有 123，后面 456 里找到了4 (只匹配一个)，剩下56用于后续匹配，于是很开森的， www 前面有 56，后面有 7，匹配到了，再往后看 .89 前面没数字，略过，因为没匹配到所以顺延到“你好”字符上，这个字符前面有89，后面有0，很好又匹配到了，最后的01匹配不到，所以最后结果是 ‘world’, ‘www’, '你好‘，结果还是正确

正则表达式写之前脑子里一定要先过一遍，匹配过的不会介入下一次匹配，你用的是 findall，你要用 match 或 search 则只匹配一次，行为又不一样了。

你的疑问是 \d+ 在字符串末尾产生了不同的结果，以为它有多个匹配行为，但实际上从头到尾 \d 都表示匹配数字， + 则表示最少匹配一次或多次，原则一直没变，变的是匹配一次后余下的字符是动态的，你的脑子里没一轮轮的去过滤匹配字符串，一直都拿原始字符串去过滤，所以看到结果摸不到头脑

---

<div class="post-metadata">

作者： ![Hoothin](https://meta-edge.appinn.com/user_avatar/meta.appinn.net/hoothin/32/31202_2.png) [@Hoothin](https://meta.appinn.net/u/Hoothin)\
发布日期： [2023 年5 月 16 日 07:05 UTC](https://meta.appinn.net/t/topic/43691/4 "2023-05-16T07:05:46Z")

</div>

python 正则匹配即丢弃。可以用断言

```python
match = re.findall(r'(?<=\d)(\D+)(?=\d)', s)

```

另外 re 的断言限宽。因此如果是其他案例（例如\d+abcd这类）需要安装 regex 模块

---

<div class="post-metadata">

作者： ![zzl221000](https://meta-edge.appinn.com/user_avatar/meta.appinn.net/zzl221000/32/15136_2.png) [@zzl221000](https://meta.appinn.net/u/zzl221000)\
发布日期： [2023 年5 月 17 日 00:31 UTC](https://meta.appinn.net/t/topic/43691/5 "2023-05-17T00:31:21Z")

</div>

```auto
r'\d+(?:\D+)'
['123world', '456www', '7.', '89你好']

```

```auto
r'\d+(?:\D+)\d+'
['123world456', '7.89']

```

```auto
r'\d+(?:\D+)\d'
['123world4', '56www7', '89你好0']

```

用非捕获组，就能清晰的看到为什么了
