正则表达式匹配数字:教程与实例 – wiki基地

正则表达式匹配数字:教程与实例

正则表达式 (Regular Expression, 简称 RegEx 或 RegExp) 是一种强大的文本处理工具,它用一套特殊的字符串模式来描述、匹配和处理字符串。在数据清洗、表单验证、日志分析等众多场景中,匹配数字是正则表达式最常见的应用之一。本文将详细介绍如何使用正则表达式来匹配不同类型的数字,并提供丰富的实例。

1. 正则表达式基础回顾

在深入匹配数字之前,我们先回顾一些基本的正则表达式元字符:

  • \d: 匹配任意一个数字 (0-9)。
  • \D: 匹配任意一个非数字字符。
  • +: 匹配前一个字符或组一次或多次 (至少一次)。
  • *: 匹配前一个字符或组零次或多次 (可以没有)。
  • ?: 匹配前一个字符或组零次或一次 (可选)。
  • {n}: 匹配前一个字符或组恰好 n 次。
  • {n,}: 匹配前一个字符或组至少 n 次。
  • {n,m}: 匹配前一个字符或组 nm 次。
  • ^: 匹配字符串的开头 (或行的开头,取决于模式选项)。
  • $: 匹配字符串的结尾 (或行的结尾,取决于模式选项)。
  • \b: 匹配单词边界。

2. 匹配基本数字

2.1 匹配单个数字

最简单的匹配就是单个数字。

  • 模式: \d
  • 解释: 匹配任何一个数字字符 (0到9)。
  • 示例:
    • 字符串: “我有 123 个苹果。”
    • 匹配结果: “1”, “2”, “3”

2.2 匹配一个或多个连续数字 (整数)

当我们需要匹配一个完整的整数时,我们通常会匹配一个或多个数字。

  • 模式: \d+
  • 解释: 匹配一个或多个连续的数字。
  • 示例:
    • 字符串: “订单号是 20231225,金额是 100.50 元。”
    • 匹配结果: “20231225”, “100”, “50” (注意会把小数点前后的数字分开匹配)

2.3 匹配零个或多个连续数字

在某些情况下,可能需要匹配零个或多个数字,但这在匹配实际数字时较少单独使用,因为 \d* 甚至可以匹配空字符串。

  • 模式: \d*
  • 解释: 匹配零个或多个连续的数字。
  • 示例:
    • 字符串: “空白 数字”
    • 匹配结果: 在 “空白” 和 “数字” 之间,以及字符串开头和结尾,都会有空匹配。在 “数字” 中会匹配 “字” 之前的空和 “字” 之后的空。在”数字”二字之间,”字”之后,也会有匹配。当用于数字提取时,通常与 +? 配合使用。

2.4 匹配特定长度的数字

如果你需要匹配固定位数的数字,例如四位年份或六位验证码。

  • 模式: \d{n}
  • 解释: 匹配恰好 n 个连续的数字。
  • 示例:
    • 字符串: “年份 2023, 编号 12345, 验证码 6789”
    • 模式 \d{4} 匹配结果: “2023”, “6789”

2.5 匹配指定范围长度的数字

当数字的长度在一个范围内时。

  • 模式: \d{n,m} (n 到 m 位) 或 \d{n,} (至少 n 位)
  • 解释:
    • \d{n,m}: 匹配 nm 个连续的数字。
    • \d{n,}: 匹配至少 n 个连续的数字。
  • 示例:
    • 字符串: “数字1: 123, 数字2: 12345, 数字3: 9”
    • 模式 \d{3,5} 匹配结果: “123”, “12345”
    • 模式 \d{2,} 匹配结果: “123”, “12345”, “9” (如果后面还有其他数字字符,例如99,也会匹配99)

3. 匹配整数 (带符号)

整数可以是正数、负数或零。

3.1 匹配不带符号的正整数或零

  • 模式: \d+ (已包含)

3.2 匹配带符号的整数

整数可能带 +- 前缀。

  • 模式: [+-]?\d+
  • 解释:
    • [+-]?: 匹配可选的 +- 符号。? 使其成为可选。
    • \d+: 匹配一个或多个数字。
  • 示例:
    • 字符串: “温度是 +25C, 余额 -100元, 存款 5000。”
    • 匹配结果: “+25”, “-100”, “5000”

4. 匹配浮点数 (小数)

浮点数包含一个小数点。

4.1 匹配标准浮点数 (整数部分.小数部分)

  • 模式: \d+\.\d+
  • 解释:
    • \d+: 匹配整数部分 (至少一个数字)。
    • \.: 匹配字面量的小数点 (注意需要用 \ 转义,因为 . 在正则表达式中有特殊含义,表示匹配任何字符)。
    • \d+: 匹配小数部分 (至少一个数字)。
  • 示例:
    • 字符串: “价格 19.99, 温度 36.5, 数量 100。”
    • 匹配结果: “19.99”, “36.5”

4.2 匹配包含可选整数部分或小数部分的浮点数

例如,.510. 这样的写法。

  • 模式: [+-]?(\d+\.\d*|\.\d+|\d+)
  • 解释: 这是一个更复杂的模式,用于匹配各种形式的浮点数和整数。
    • [+-]?: 可选的符号。
    • (\d+\.\d*|\.\d+|\d+): 使用 | (或) 运算符来匹配三种情况:
      1. \d+\.\d*: 匹配 123., 123.45 (整数部分,可选小数部分)。
      2. \.\d+: 匹配 .45 (无整数部分,有小数部分)。
      3. \d+: 匹配 123 (纯整数)。
  • 示例:
    • 字符串: “值是 +10.5, 还有 .75, 另一个是 200, 和 -5.。”
    • 匹配结果: “+10.5”, “.75”, “200”, “-5.”

更简洁且常用[+-]?\d*\.?\d+
这个模式可以匹配以下情况:
* 123 (整数)
* +123
* -123
* 123.45
* +123.45
* -123.45
* .45 (小数开头)
* +.45
* -.45

不能匹配:123.. (因为 \d+ 要求至少有一个数字)

如果要匹配 123. 这种形式,可以使用:
[+-]?(\d+\.?\d*|\d*\.\d+)
这可以匹配:123, 123., .123, 123.45

5. 结合锚点和边界

为了更精确地匹配独立的数字,而不是数字子串,我们经常使用锚点 (^, $) 和单词边界 (\b)。

5.1 匹配整个字符串就是一个数字

  • 模式: ^\d+$ (匹配纯整数)
  • 解释: 确保整个字符串从头到尾都是数字。
  • 示例:
    • 字符串: “12345” (匹配)
    • 字符串: “12345a” (不匹配)

5.2 匹配独立数字 (单词边界)

当数字是文本中的一个独立“单词”时。

  • 模式: \b[+-]?\d+(\.\d+)?\b
  • 解释:
    • \b: 匹配单词边界,确保匹配的数字不是其他单词的一部分。
    • [+-]?: 可选符号。
    • \d+: 整数部分。
    • (\.\d+)?: 可选的小数部分 (. 和后面的数字)。
  • 示例:
    • 字符串: “版本号是 1.0.5,价格 99.99,ID为abc123def。”
    • 匹配结果: “1”, “0”, “5”, “99.99” (如果 . 后有数字才匹配小数,此处 1.0.5 会被拆分。如果需要匹配完整的版本号,需要调整模式)。
    • 如果需要匹配 1.0.5 这样的版本号,模式可能需要更具体,例如 \b\d+(\.\d+){0,2}\b 来匹配至多两个小数点的数字。

6. 匹配特定格式的数字

在实际应用中,数字往往有特定的格式,例如电话号码、邮政编码、货币等。

6.1 电话号码 (例如:XXX-XXX-XXXX)

  • 模式: \b\d{3}-\d{3}-\d{4}\b
  • 解释:
    • \b: 单词边界。
    • \d{3}: 三个数字。
    • -: 字面量短横线。
    • \d{4}: 四个数字。
  • 示例:
    • 字符串: “请联系我 123-456-7890 或 987-654-3210。”
    • 匹配结果: “123-456-7890”, “987-654-3210”

6.2 邮政编码 (例如:五位数字或五位-四位)

  • 模式: \b\d{5}(-\d{4})?\b
  • 解释:
    • \d{5}: 五位数字。
    • (-\d{4})?: 可选的短横线和四位数字。
  • 示例:
    • 字符串: “地址编码 12345 或 98765-4321。”
    • 匹配结果: “12345”, “98765-4321”

6.3 货币金额 (例如:$123.45 或 ¥1,234.56)

匹配货币通常更复杂,因为它涉及货币符号、千位分隔符和可选小数。

  • 模式: [¥$€]?\s*\d{1,3}(?:,\d{3})*(?:\.\d{2})? (这是一个相对通用的模式,但可能不完美匹配所有国家的习惯)
  • 解释:
    • [¥$€]?: 可选的货币符号 (匹配人民币、美元、欧元,可根据需要增减)。
    • \s*: 零个或多个空格。
    • \d{1,3}: 开头的1到3位数字 (例如 1, 12, 123)。
    • (?:,\d{3})*: (?:...) 是非捕获组,用于分组但不创建新的匹配项。 , 后面跟三位数字,* 表示这个模式可以重复零次或多次 (匹配千位分隔符)。
    • (?:\.\d{2})?: 可选的小数点和两位小数。
  • 示例:
    • 字符串: “商品价格是 $1,234.56, 另一个是 ¥99.00, 还有 500。”
    • 匹配结果: “$1,234.56”, “¥99.00”, “500”

7. 编程语言中的应用 (以 Python 为例)

大多数编程语言都有内置的正则表达式模块。在 Python 中,是 re 模块。

“`python
import re

text = “订单号: 20230101, 金额: +123.45元, 数量: 50, 负数: -10.0, 版本: 1.0.2, 电话: 138-0013-8000”

匹配所有整数

pattern_integers = r”\b[+-]?\d+\b”
matches = re.findall(pattern_integers, text)
print(f”整数匹配: {matches}”) # [‘20230101’, ‘+123′, ’50’, ‘-10’]

匹配所有浮点数 (含整数)

尽可能匹配完整的数字,包括小数

pattern_numbers = r”[+-]?\d*.?\d+”
matches = re.findall(pattern_numbers, text)
print(f”通用数字匹配: {matches}”) # [‘20230101’, ‘+123.45′, ’50’, ‘-10.0’, ‘1.0’, ‘2’, ‘138’, ‘0013’, ‘8000’]

注意:这会把 1.0.2 分成 1.0 和 2。 如果要匹配完整的版本号,需要更精细的模式。

匹配电话号码

pattern_phone = r”\b\d{3}-\d{3}-\d{4}\b”
matches = re.findall(pattern_phone, text)
print(f”电话号码匹配: {matches}”) # [‘138-0013-8000’]

匹配版本号 (例如 X.Y.Z)

pattern_version = r”\b\d+(.\d+){1,2}\b” # 至少一个小数点,至多两个
matches = re.findall(pattern_version, text)
print(f”版本号匹配: {matches}”) # [‘1.0.2’, ‘.0’, ‘.2’] – 捕获组会独立返回。

更好的匹配版本号 (非捕获组)

pattern_version_better = r”\b\d+(?:.\d+){1,2}\b”
matches = re.findall(pattern_version_better, text)
print(f”优化版本号匹配: {matches}”) # [‘1.0.2’]
“`

8. 总结与最佳实践

  • 明确需求: 在编写正则表达式之前,清楚地定义你需要匹配的数字类型 (整数、浮点数、特定格式)。
  • 转义特殊字符: .+*?()[]{}^$|\ 都是正则表达式的元字符,如果需要匹配它们本身,需要使用 \ 进行转义。
  • 使用锚点和边界: ^, $, \b 对于精确匹配非常重要,它们能帮助你匹配独立的数字,而不是包含在其他文本中的数字片段。
  • 贪婪与非贪婪: 默认情况下,量词 (*, +, ?, {n,m}) 是贪婪的,会尽可能多地匹配。在其后添加 ? 可以使其变为非贪婪模式 (例如 *?, +?),尽可能少地匹配。这在匹配 HTML 标签等特定场景中很有用,但在匹配数字时通常不是主要考虑因素。
  • 测试你的正则表达式: 使用在线正则表达式测试工具 (如 Regex101.com, RegExr.com) 是一个非常好的习惯,可以实时看到匹配效果并调试模式。
  • 编程语言特性: 了解你所使用的编程语言中正则表达式模块的特定函数和标志位 (例如 Python 的 re.findall, re.search, re.match, re.IGNORECASE 等)。

掌握正则表达式匹配数字的技巧将极大提升你的文本处理能力。通过理解基本元字符和量词的组合,你可以构建出精确而高效的模式,应对各种复杂的数字匹配需求。

滚动至顶部