使用正则表达式从右到左将数字分成三组

Splitting digits into groups of threes, from right to left using regular expressions

我有一个字符串“1234567890”,我想将其分成三组,从右到左,最左边的组从一位到三位不等(取决于剩下多少位)

本质上,这与向长数字添加逗号的过程相同,除了,我还想提取最后三位数字。

我尝试使用环顾四周,但无法找到获得最后三个的方法 数字。

string = '1234567890'
re.compile(r'\d{1,3}(?=(?:\d{3})+$)')
re.findall(pattern, string)

['1', '234', '567']

预期输出是(我不需要逗号):

 ['1', '234', '567', 789]

请注意,如果我们从右到左添加逗号,对于每组三个完整的数字,那么我们可以简单地做一个正则表达式,用这三个数字后跟一个逗号替换所有三个数字。在下面的代码片段中,我反转数字字符串,进行逗号处理,然后再次反转以达到我们想要的输出。

string = '1234567890'
string = re.sub(r'(?=\d{4})(\d{3})', r',', string[::-1])[::-1]
print string.split(',')
string = '123456789'
string = re.sub(r'(?=\d{4})(\d{3})', r',', string[::-1])[::-1]
print string.split(',')

输出:

['1', '234', '567', '890']
['123', '456', '789']

用于替换的正则表达式的一部分可能需要进一步解释。我在模式的开头添加了正向前瞻 (?=\d{4})。这是为了确保我们不会在最后一组三位数后添加逗号,如果发生的话。

此处演示:

Rextester

实际上更容易对反向字符串进行操作以跟踪有更多数字的 3 位数字组(使用正前瞻 (?=\d):

for s in ('123','1234','123456789','1234567890'):
    print(re.sub(r'(\d\d\d)(?=\d)',r',',s[::-1])[::-1])

或否定前瞻版本:

for s in ('123','1234','123456789','1234567890'):
    print(re.sub(r'(\d\d\d)(?!$)',r',',s[::-1])[::-1])

要么打印:

123
1,234
123,456,789
1,234,567,890

在反转字符串上应用反转正则表达式在 Perl 中称为 sexeger ;-)

你也可以做一个不需要反转字符串的前瞻版本:

for s in ('123','1234','123456789','1234567890'):
   print(re.sub(r'(\d)(?=(\d{3})+$)',r',',s))
# same output

根据评论,只需添加一个适当的分隔符,然后 .split 就可以了:

>>> for s in ('123','1234','123456789','1234567890'):
...     re.sub(r'(\d)(?=(\d{3})+$)',r'\t',s).split('\t')
... 
['123']
['1', '234']
['123', '456', '789']
['1', '234', '567', '890']

或者,跳过正则表达式,直接在 Python 中执行:

for s in ('123','1234','123456789','1234567890'):
    s=s[::-1]
    n=3
    print([s[i:i+n][::-1] for i in range(0,len(s),n)][::-1])
# same output

你们非常亲密。问题是当你在最后一组时,前瞻子表达式中的 + 会使整个表达式失败,因为不会有 1 到 3 位数字的组后跟至少一组 3 位数字数字(这是先行子表达式指定的内容)。

想想当你尝试 123 时会发生什么。仅当有一组 1 到 3 位数字后跟 至少一个 组 3 位数字时,您的表达式才会匹配。在这种情况下不会发生这种情况,因为 3 位数字组 123 后面没有任何内容,因此表达式将失败,并且该组不会包含在输出中。

只需将 + 更改为 * 即可解决问题,因为在当前的 1 到 3 位数字组之后不需要任何 3 位数字组的顺序匹配:

>>> pattern = re.compile(r'\d{1,3}(?=(?:\d{3})*$)')
>>> pattern.findall('1')
['1']
>>> pattern.findall('123')
['123']
>>> pattern.findall('1234')
['1', '234']
>>> pattern.findall('123456789')
['123', '456', '789']
>>> pattern.findall('1234567890')
['1', '234', '567', '890']
>>> pattern.findall('')
[]