匹配(法语)数字的正则表达式

Regex to match (French) numbers

我试图找到一种简单(不完美)的模式来识别法语文本中的法语数字。法语数字使用逗号表示盎格鲁-撒克逊小数点,使用点或 space 作为千位分隔符。 \u00A0 是不间断的 space,也常用于法语文档中的千位分隔符。

所以我的第一次尝试是:

number_pattern = re.compile(r'\d[\d\., \u00A0]*\d', flags=re.UNICODE)

...但问题是这与单个数字不匹配。

但如果我这样做

number_pattern = re.compile(r'\d[\d\., \u00A0]*\d?', flags=re.UNICODE)

然后它会拾取尾随 space(或 NBS)字符(或尾随逗号或句号)。

事实是,模式必须以数字开始和结束,但这些可能是相同的字符。

我怎样才能做到这一点?我考虑了一个两阶段过程,您尝试查看这是否实际上是一个单位数……但这本身并不简单:如果后跟 space、NBS、逗号或点,您然后要看that后面的字符是否是数字

显然我希望找到一种只涉及一个正则表达式的解决方案:如果只有一个正则表达式,则可以执行以下操作:

doubled_dollars_plain_text = plain_text.replace('$', '$$')
substituted_plain_text = re.sub(number_pattern, '$number', doubled_dollars_plain_text)

...必须使用两阶段过程会使这变得更加冗长和繁琐。

编辑

我试图看看我是否可以实现 ThierryLathuille 的想法,所以我尝试了:

re.compile(r'(\d(?:[\d\., \u00A0]*\d)?)', flags=re.UNICODE)

...这似乎工作得很好。与 JvdV 的解决方案不同,它不会尝试检查千位分隔符后跟 3 位数字,就此而言,你可以在中间有连续的逗号和 spaces,它仍然会通过,这是很有问题的当你有一个由“,”分隔的数字列表时。但出于某些目的,它是可以接受的……直到找到更复杂的东西。

我想知道是否有一种说法“此模式中的任何非数字必须独立存在”(即必须用括号括在两位数字之间)?

怎么样:

\d{1,3}(?:[\s.]?\d{3})*(?:,\d+)?(?!\d)

在线查看demo

  • \d{1,3} - 1-3 位数字。
  • (?: - 打开第一个非捕获组:
    • [\s.]? - 一个可选的空格或文字点。请注意,使用 unicode \s 应该匹配 \p{Z} 以包含不间断空格。
    • \d{3} - 三位数。
    • )* - 关闭第一个非捕获组并匹配 0+ 次。
  • (?:,\d+)? - 第二个可选的非捕获组,用于匹配逗号后跟至少 1 个数字。
  • (?!\d) - 否定前瞻以防止尾随数字。

受到 JvdV 回答的启发,我建议:

number_pattern = re.compile(r'(\d{1,3}(?:(?:[. \u00A0])?\d{3})*(?:,\d+)?(?!\d))',  flags=re.UNICODE)

... 这使得千位分隔符成为可选的,并且也使得千位组成为可选的。它将千位分隔符限制为 3 个可能的字符:点、space 和 NBS,这在实践中对于法语数字是必需的。

PS我今天才发现,实际上讲瑞士法语的人有时会使用撇号(在浩瀚的 Unicode 中有几个候选者)作为千位分隔符。