Python正则表达式用空格全局替换尾随的零

2024-09-27 23:25:44 发布

您现在位置:Python中文网/ 问答频道 /正文

为了解决将浮点数与表格式数字数据的十进制分隔符对齐的问题,我尝试使用以下规则找到一个正则表达式,将(全局后验)尾随的零替换为空格:

  1. 小数后没有尾随的零
  2. 如果小数分隔符后的第一个数字是零,则保留它

由于pythonregex引擎对look-behind要求固定宽度模式的限制,我无法找到一个令人满意的解决方案。以下是我的尝试(Python 3.x)的一个有效示例;在解决方案中不依赖垂直条,在示例中只是为了清晰起见:

import re
# formatmany is just a way to speed up building of multiline string of tabular data
formatmany=lambda f:lambda *s:'\n'.join(f.format(*x) for x in s)

my_list = [[12345, 12.345, 12.345, 12.345],
           [12340, 12.34 , 12.34 , 12.34 ],
           [12345, 12.005, 12.005, 12.005],
           [12340, 12.04 , 12.04 , 12.04 ],
           [12300, 12.3  , 12.3  , 12.3  ],
           [12000, 12.0  , 12.0  , 12    ]]
my_format = formatmany('|{:8d}|{:8.2f}|{:8.3f}|{:8.4f}|')
my_string = my_format(*my_list) # this is the formatted multiline string with trailing zeros

print('\nOriginal string:\n')
print(my_string)
print('\nTry 1:\n')
print(re.sub(r'(?<!\.)0+(?=[^0-9\.]|$)',lambda m:' '*len(m.group()),my_string))
print('\nTry 2:\n')
print(re.sub(r'(\d)0+(?=[^\d]|$)',r'\1',my_string))

哪个指纹

^{pr2}$

Try 1替换尾随的零也在整数中,Try 2取自另一个在单个浮点中替换尾随零的解决方案。两者都不令人满意,因为期望的输出应为:

|   12345|   12.35|  12.345| 12.345 |
|   12340|   12.34|  12.34 | 12.34  |
|   12345|   12.01|  12.005| 12.005 |
|   12340|   12.04|  12.04 | 12.04  |
|   12300|   12.3 |  12.3  | 12.3   |
|   12000|   12.0 |  12.0  | 12.0   |

为什么这不是一个重复的问题

  1. Python正则表达式引擎与其他语言引擎略有不同,因此针对其他语言的解决方案不会自动应用
  2. 后面的零将被替换,而不是去掉
  3. 这是关于全局替换多行字符串中的多个事件,而不仅仅是单个事件

Tags: lambda引擎reformat示例stringismy
3条回答

您需要按如下方式更改sub

print(re.sub(r'(?<=\.)([0-9]+?)(0+)(?=\D|$)',lambda m:m.group(1)+' '*len(m.group(2)), my_string))

IDEONE demo

这是a demo of what ^{} regex matches。在

正则表达式匹配:

  • (?<=\.)([0-9]+?)-1个或更多的数字,但如果前面有一个文本.(十进制分隔符),则应尽可能少地使用
  • (0+)-1个或更多个零。。。在
  • (?=\D|$)-最多一个非数字\D或字符串结尾{}。在

另一种方法是:

my_list = [[12345, 12.345, 12.345, 12.345],
           [12340, 12.340, 12.340, 12.340],
           [12300, 12.300, 12.300, 12.300],
           [12000, 12.000, 12.000, 12.000]]

format_list = ["{:8d}", "{:8.2f}", "{:8.3f}", "{:8.4f}"]

for row in my_list:
    line = ["{:<8}".format(re.sub(r'(\.\d+?)0+', r'\1', y.format(x))) for x,y in zip(row, format_list)]
    print("|{}|".format("|".join(line)))

给出输出:

^{pr2}$

斯特里比雪夫(以前但不满意)的回答让我想到了一个普遍的解决办法:

re.sub(r'(?<=\.)(\d+?)(0+)(?=[^\d]|$)',lambda m:m.group(1)+' '*len(m.group(2))

相关问题 更多 >

    热门问题