匹配(法语)数字的正则表达式
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 中有几个候选者)作为千位分隔符。
我试图找到一种简单(不完美)的模式来识别法语文本中的法语数字。法语数字使用逗号表示盎格鲁-撒克逊小数点,使用点或 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 中有几个候选者)作为千位分隔符。